12

Actualmente tengo mi aplicación configurada con un ListFragment a la izquierda y un DetailsFragment a la derecha (similar al diseño en la tableta a continuación).WebViewFragment webView es nulo después de hacer un FragmentTransaction

layout

En el fragmento de datos (fragmento lado de la lista) Tengo un botón de trato Goto, que al ser presionado debe reemplazar el detailsFragment con un WebViewFragment.

El problema que tengo es que cuando intento cargar una url en el fragmento webviewf WebView es nulo.

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"); 

A continuación se muestra mi diseño principal que tiene los dos fragmentos originales definidos.

<?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> 

Parece que el webViewFragment no se está creando plenamente como el WebView no se ha inicializado. He buscado en línea, pero hay muy poca información sobre el WebViewFragment.

Alguna idea de cómo asegurar WebView se inicializa en el WebViewFragment?

+0

Por favor enviar el código para su clase DealWebViewFragment. – Jonathan

+0

@Jonathan - Lo siento, mi DealWebViewFragment fue solo una recreación de WebViewFragment. He cambiado el código anterior a WebViewFragment (existe el mismo problema). – bencallis

Respuesta

12

Con la gran ayuda de Espiandev, he logrado obtener un WebView en funcionamiento. Para asegurar que los enlaces se abrieron en el fragmento y no en una aplicación de navegador web, creé un cliente InnerWebView simple que extiende 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; 
     } 


    } 

Esperemos que esto sea útil para alguien en el futuro.

0

Los fragmentos solo pueden reemplazarse si se inicializaron en Java, no en XML. Creo que sí, tuve el mismo problema y lo resolvió. Cambiar el código XML a esto:

<?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> 

y luego en Java, el método onCreate:

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

o incluso mejor método create conjunto para hacer frente a solo Transaction s.

Ahora Transaction de su pregunta debería funcionar. :)

+0

Gracias por la ayuda. He cambiado mi diseño reemplazando el fragmento con una vista. En mi actividad principal, agregué el siguiente \t \t FragmentTransaction transaction = getFragmentManager(). BeginTransaction(); \t transaction.replace (R.id.right_fragment_container, new DealDetailsFragment(), "dealDetailsFragment"); \t transaction.commit(); Desafortunadamente, esto está dando como resultado una excepción Java.lang.ClassCastException: android.view.View no se puede convertir a android.view.ViewGroup – bencallis

+0

He ordenado esta excepción de hechizo utilizando LinearLayout en lugar de Ver. La aplicación ahora se ejecuta, pero al presionar ir a ofertas, no se puede cargar una url ya que webView sigue siendo nulo. – bencallis

7

EDITAR: Así que jugué con esto por un tiempo y parece que el WVF es un poco basura y está diseñado para ser anulado. Sin embargo, ¡no hay documentación sobre esto en absoluto! El problema se debe al hecho de que puede llamar a getWebView() antes de que se cargue la vista Fragment, de ahí su NullPointerException. Excepto que no hay forma de detectar cuándo se ha cargado la vista del Fragmento, ¡así que estás atascado!

En su lugar anulé la clase, añadí bits y cambio de bits, por lo que ahora funcionará bien. Compruebe this link para el código. A continuación, en lugar de utilizar:

WebViewFragment webViewFragment = new WebViewFragment(); 

para cargar el fragmento, utilice:

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

Esta clase también incluye un método de conveniencia para cargar una URL, que no se lanzar una Exception si no hay WebView.

Así que, no, no creo que haya una manera particularmente simple de usar el WebViewFragment integrado, pero es bastante fácil hacer algo que funcione en su lugar. ¡Espero eso ayude!

+0

Estoy usando el built-in Android WebViewFragment [link] http://developer.android.com/reference/android/webkit/WebViewFragment.html. Puedo buscar hacer mi propio pero seguramente debería ser capaz de construir uno. – bencallis

+0

oh sí, lo siento, no me di cuenta. Tendré un violín con el código que has publicado y veré si puedo ayudar. –

+0

Gracias. ¿Tuviste un poco de suerte? – bencallis

3

WebViewFragmento como no es tan fácil de usar. Pruebe esta simple extensión (Puede copiar/pegar):

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; 
    }   
    } 

de llamadas donde se necesita utilizar el método de fábrica:

WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com"); 
Cuestiones relacionadas