Search code examples
androidandroid-3.0-honeycombandroid-webviewandroid-fragmentsandroid-4.0-ice-cream-sandwich

WebViewFragment webView is null after doing a FragmentTransaction


I currently have my application set up with a ListFragment on the left and a DetailsFragment on the right (similar to the layout on the tablet below).

layout

On the details fragment (fragment next to the list) I have a goto deal button, which when pressed should replace the detailsFragment with a WebViewFragment.

The problem I am having is that when trying to load a url in the webviewfragment the WebView is 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");

Below is my main layout which has the original two fragments defined.

<?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: layout=@layout/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: layout=@layout/deal_details_fragment -->
  </fragment>

</LinearLayout>

It seems that the webViewFragment is not being created fully as the WebView has not been initialised. I have looked online but there is very little information regarding the WebViewFragment.

Any ideas how to ensure WebView is initialised in the WebViewFragment?


Solution

  • With great help from Espiandev I have managed to get a working WebView. To ensure that links opened in the fragment and not in a web browser application I created a simple InnerWebView client which extends 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;
            }
    
    
        }
    

    Hopefully this is useful to someone in the future.