12

我目前已經在左側設置了ListFragment,在右側設置了DetailsFragment(類似於下面的平板電腦上的佈局)。做一個FragmentTransaction後,WebViewFragment的webView爲空

layout

在細節片段(列表旁邊的片段)我有一個轉到的交易按鈕,按下該按鈕應以WebViewFragment更換detailsFragment時。

我遇到的問題是,當試圖在webviewfragment中加載url時,WebView爲空。

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

下面是我的主要佈局,其中定義了原始的兩個片段。

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

似乎沒有完全被創建webViewFragment作爲WebView尚未初始化。我在網上查找過,但關於WebViewFragment的信息很少。

任何想法如何確保WebView初始化在WebViewFragment

+0

請張貼代碼爲您DealWebViewFragment類。 – Jonathan 2012-02-06 14:12:52

+0

@Jonathan - 對不起,我的DealWebViewFragment只是重新創建了WebViewFragment。我已將上面的代碼更改回WebViewFragment(存在同樣的問題)。 – bencallis 2012-02-06 18:16:04

回答

12

在Espiandev的大力幫助下,我設法獲得了一個可用的WebView。爲了確保在片段中而不是在瀏覽器應用程序中打開鏈接,我創建了一個擴展WebViewClinet的簡單InnerWebView客戶端。

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


    } 

希望這對未來某個人有用。

0

碎片只能在Java中初始化而不是XML中被替換。我想是的,我有同樣的問題,它解決了它。你的XML改成這樣:

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

,然後在Java中,你onCreate方法:

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

,甚至更好地創造整個方法只是處理Transaction秒。

現在Transaction從你的問題應該工作。 :)

+0

感謝您的幫助。我改變了我的佈局替換片段與視圖。 在我的主要活動中,我添加了以下內容 \t \t FragmentTransaction transaction = getFragmentManager()。beginTransaction(); transaction.replace(R.id.right_fragment_container,new DealDetailsFragment(),「dealDetailsFragment」); \t transaction.commit(); 不幸的是,這導致了一個Java.lang.ClassCastException:android.view.View不能轉換爲android.view.ViewGroup – bencallis 2012-02-06 18:10:48

+0

我已經使用LinearLayout而不是View對這個轉換異常進行了排序。應用程序現在可以運行,但當按下去處理時,url不能被加載,因爲webView仍然是空的。 – bencallis 2012-02-06 18:32:44

7

編輯:所以我玩了這一段時間,似乎WVF是有點垃圾和設計被覆蓋。但是,根本沒有這方面的文檔!這個問題源於在加載Fragment的視圖之前可以調用getWebView(),因此您的NullPointerException。除了沒有辦法檢測Fragment的視圖何時加載,所以你有點卡住了!

相反,我重寫了類,添加了一些位並更改了一些位,這樣它就可以正常工作。 檢查this link的代碼。 。然後,而不是使用:

WebViewFragment webViewFragment = new WebViewFragment(); 

加載您的片段,使用:

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

此類還包括一個方便的方法,用於加載URL,即不會拋出Exception如果沒有WebView

所以,不,我不認爲使用內置的WebViewFragment有一個特別簡單的方法,但是相反,它可以很容易地生成。希望能幫助到你!

+0

我使用內置的Android WebViewFragment [鏈接] http://developer.android.com/reference/android/webkit/WebViewFragment.html。我可以考慮製作自己的作品,但我肯定應該可以製作成一個。 – bencallis 2012-02-08 16:34:34

+0

哦,是的,抱歉沒有意識到。我會弄清楚你發佈的代碼,看看我能否提供幫助。 – 2012-02-08 17:56:19

+0

謝謝。你有沒有運氣? – bencallis 2012-02-09 13:29:08

3

WebViewFragment as is is not that straightforward use。試試這個簡單的擴展(您可以複製/粘貼):

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

呼叫,你需要使用工廠方法:

WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com"); 
相關問題