12

Obecnie mam skonfigurowaną aplikację z ListFragment po lewej stronie i DetailsFragment po prawej stronie (podobnie jak w układzie na tablecie poniżej).WebViewFragment webView ma wartość null po wykonaniu FragmentTransaction

layout

na fragmencie Szczegóły (fragment obok listy) Mam przycisk deal Goto, który po naciśnięciu powinien zastąpić detailsFragment z WebViewFragment.

Problem polega na tym, że podczas próby załadowania adresu URL w widoku podglądu strony internetowej WebView ma wartość null.

WebViewFragment webViewFragment = new WebViewFragment(); 

FragmentTransaction transaction = getFragmentManager().beginTransaction(); 

// Replace whatever is in the fragment_container view with this fragment, 
// and add the transaction to the back stack 
transaction.replace(R.id.deal_details_fragment, webViewFragment); 
transaction.addToBackStack(null); 

// Commit the transaction 
transaction.commit(); 

// Set the url 
if (webViewFragment.getWebView()==null) 
    Log.d("webviewfragment", "is null"); 
webViewFragment.getWebView().loadUrl("http://www.google.com"); 

Poniżej znajduje się mój główny układ zawierający oryginalne dwa fragmenty.

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/main_activity_layout" 

    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" > 

    <fragment 
     android:name="com.bencallis.dealpad.DealListFragment" 
     android:id="@+id/deal_list_fragment" 
     android:layout_weight="1" 
     android:layout_width="0px" 
     android:layout_height="match_parent" > 
     <!-- Preview: [email protected]/deal_list_fragment --> 
    </fragment> 
    <fragment 
     android:name="com.bencallis.dealpad.DealDetailsFragment" 
     android:id="@+id/deal_details_fragment" 
     android:layout_weight="2" 
     android:layout_width="0px" 
     android:layout_height="match_parent" > 
     <!-- Preview: [email protected]/deal_details_fragment --> 
    </fragment> 

</LinearLayout> 

Wydaje się, że webViewFragment nie jest tworzony w pełni jako WebView nie został zainicjowany. Sprawdziłem online, ale jest bardzo mało informacji dotyczących WebViewFragment.

pomysłów w jaki sposób zapewnić WebView zostaje zainicjowany w WebViewFragment?

+0

proszę pisać kod dla klasy DealWebViewFragment. – Jonathan

+0

@ Jonathan - Przepraszam, że mój DealWebViewFragment był po prostu odtwarzaniem WebViewFragment. Zmieniłem powyższy kod z powrotem na WebViewFragment (ten sam problem istnieje). – bencallis

Odpowiedz

12

Przy pomocy Espiandeva udało mi się uzyskać działający WebView. Aby zapewnić, że linki otwierają się w fragmencie, a nie w aplikacji przeglądarki internetowej, utworzyłem prosty klient InnerWebView, który rozszerza WebViewClinet.

public class DealWebViewFragment extends Fragment { 

    private WebView mWebView; 
    private boolean mIsWebViewAvailable; 
    private String mUrl = null; 

    /** 
    * Creates a new fragment which loads the supplied url as soon as it can 
    * @param url the url to load once initialised 
    */ 
    public DealWebViewFragment(String url) { 
     super(); 
     mUrl = url; 
    } 

    /** 
    * Called to instantiate the view. Creates and returns the WebView. 
    */ 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     if (mWebView != null) { 
      mWebView.destroy(); 
     } 
     mWebView = new WebView(getActivity()); 
     mWebView.setOnKeyListener(new OnKeyListener(){ 


      @Override 
      public boolean onKey(View v, int keyCode, KeyEvent event) { 
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { 
         mWebView.goBack(); 
         return true; 
        } 
        return false; 
      } 

     }); 
     mWebView.setWebViewClient(new InnerWebViewClient()); // forces it to open in app 
     mWebView.loadUrl(mUrl); 
     mIsWebViewAvailable = true; 
     WebSettings settings = mWebView.getSettings(); 
     settings.setJavaScriptEnabled(true); 
     return mWebView; 
    } 

    /** 
    * Convenience method for loading a url. Will fail if {@link View} is not initialised (but won't throw an {@link Exception}) 
    * @param url 
    */ 
    public void loadUrl(String url) { 
     if (mIsWebViewAvailable) getWebView().loadUrl(mUrl = url); 
     else Log.w("ImprovedWebViewFragment", "WebView cannot be found. Check the view and fragment have been loaded."); 
    } 

    /** 
    * Called when the fragment is visible to the user and actively running. Resumes the WebView. 
    */ 
    @Override 
    public void onPause() { 
     super.onPause(); 
     mWebView.onPause(); 
    } 

    /** 
    * Called when the fragment is no longer resumed. Pauses the WebView. 
    */ 
    @Override 
    public void onResume() { 
     mWebView.onResume(); 
     super.onResume(); 
    } 

    /** 
    * Called when the WebView has been detached from the fragment. 
    * The WebView is no longer available after this time. 
    */ 
    @Override 
    public void onDestroyView() { 
     mIsWebViewAvailable = false; 
     super.onDestroyView(); 
    } 

    /** 
    * Called when the fragment is no longer in use. Destroys the internal state of the WebView. 
    */ 
    @Override 
    public void onDestroy() { 
     if (mWebView != null) { 
      mWebView.destroy(); 
      mWebView = null; 
     } 
     super.onDestroy(); 
    } 

    /** 
    * Gets the WebView. 
    */ 
    public WebView getWebView() { 
     return mIsWebViewAvailable ? mWebView : null; 
    } 

    /* To ensure links open within the application */ 
    private class InnerWebViewClient extends WebViewClient { 
     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      view.loadUrl(url); 
      return true; 
     } 


    } 

Mam nadzieję, że przyda się to komuś w przyszłości.

0

Fragmenty można zastąpić tylko wtedy, gdy zostały zainicjalizowane w Javie, a nie XML. Tak sądzę, miałem ten sam problem i go rozwiązałem. Zmienić XML do tego:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/main_activity_layout" 

    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" > 

    <fragment 
     android:name="com.bencallis.dealpad.DealListFragment" 
     android:id="@+id/deal_list_fragment" 
     android:layout_weight="1" 
     android:layout_width="0px" 
     android:layout_height="match_parent" > 
     <!-- Preview: [email protected]/deal_list_fragment --> 
    </fragment> 
    <View 
     android:id="@+id/my_container" 
     android:layout_weight="2" 
     android:layout_width="0px" 
     android:layout_height="match_parent" > 
    </View> 

</LinearLayout> 

a potem w Javie, swoje onCreate metody:

FragmentTransaction transaction = getFragmentManager().beginTransaction(); 
transaction.replace(R.id.my_container, new DealDetailsFragment()); 
transaction.commit(); 

lub nawet lepiej stworzyć całą metodę tylko do czynienia z Transaction s.

Teraz odpowiedź na pytanie Transaction powinna zadziałać. :)

+0

Dzięki za pomoc. Zmieniłem układ, zastępując fragment widokiem. W mojej głównej działalności dodałem następującą \t \t transakcji FragmentTransaction = getFragmentManager(). BeginTransaction(); \t transaction.replace (R.id.right_fragment_container, new DealDetailsFragment(), "dealDetailsFragment"); \t transaction.commit(); Niestety to skutkuje Java.lang.ClassCastException: android.view.View nie mogą być oddane do android.view.ViewGroup – bencallis

+0

Mam klasyfikowane ten wyjątek rzucany przez użyciem LinearLayout zamiast View. Aplikacja jest teraz uruchomiona, ale po naciśnięciu przycisku przejdź do oferty nie można załadować adresu URL, ponieważ webView nadal ma wartość null. – bencallis

7

EDYCJA: Więc bawiłem się z tym przez chwilę i wygląda na to, że WVF jest trochę bzdurą i ma być nadpisany. Jednak nie ma w tym żadnej dokumentacji! Problem wynika z faktu, że możesz wywołać metodę getWebView() przed załadowaniem widoku Fragment, stąd Twój NullPointerException. Tyle tylko, że nie ma sposobu na wykrycie, kiedy widok Fragmentu został załadowany, więc utknąłeś w pewnym sensie!

Zamiast tego przeszmuglowałem zajęcia, dodając bity i zmieniając bity, aby teraz zadziałało. Sprawdź kod w kodzie this link. Wtedy zamiast używać:

WebViewFragment webViewFragment = new WebViewFragment(); 

aby załadować fragment zastosowanie:

ImprovedWebViewFragment wvf = new ImprovedWebViewFragment("www.google.com"); 

Klasa ta obejmuje również sposób wygoda dla ładowanie url, że nie rzucić Exception jeśli nie ma WebView.

Tak, nie, nie sądzę, że istnieje wyjątkowo prosty sposób korzystania z wbudowanego WebViewFragment, ale dość łatwo jest zrobić coś, co działa. Mam nadzieję, że to pomoże!

+0

Używam wbudowanego interfejsu Android WebViewFragment [link] http://developer.android.com/reference/android/webkit/WebViewFragment.html. Mogę zaglądać w swój własny, ale na pewno powinienem móc go wbudować. – bencallis

+0

o tak, przepraszam, nie zdawałem sobie z tego sprawy. Będę miał skrzypce z opublikowanym przez ciebie kodem i zobaczę, czy mogę pomóc. –

+0

Dziękuję. Czy miałeś szczęście? – bencallis

3

WebViewFragment jako taki nie jest tak prosty w użyciu. Spróbuj tego prostego rozszerzenia (można kopiować/wklej):

public class UrlWebViewFragment extends WebViewFragment{ 

    private String url; 

    public static UrlWebViewFragment newInstance(String url) { 
     UrlWebViewFragment fragment = new UrlWebViewFragment(); 
     fragment.url = url; 
     return fragment; 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     WebView webView = (WebView) super.onCreateView(inflater, container, savedInstanceState); 
     webView.loadUrl(url); 
     return webView; 
    }   
    } 

połączeń, gdzie trzeba się metodą fabryczną:

WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com"); 
Powiązane problemy