12

В настоящее время у меня установлено мое приложение с ListFragment слева и DetailsFragment справа (аналогично расположению на планшете ниже).WebViewFragment webView имеет значение null после выполнения FragmentTransaction

layout

На детали фрагмента (фрагмент рядом со списком) У меня есть кнопка Гото сделки, которая при нажатии следует заменить detailsFragment с WebViewFragment.

Проблема, с которой я столкнулась, заключается в том, что при попытке загрузить URL-адрес в веб-фрагменте просмотра WebView имеет значение 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"); 

Ниже приведена моя основная компоновка, в которой определены исходные два фрагмента.

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

+0

@ Jonathan - Извините, мой DealWebViewFragment был всего лишь воссозданием WebViewFragment. Я изменил приведенный выше код обратно в WebViewFragment (та же проблема существует). – bencallis

ответ

12

С большой помощью от Espiandev мне удалось получить рабочий WebView. Чтобы убедиться, что ссылки открыты в фрагменте, а не в приложении веб-браузера, я создал простой клиент InnerWebView, который расширяет 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; 
     } 


    } 

Надеюсь, это полезно кому-то в будущем.

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(); \t transaction.replace (R.id.right_fragment_container, новый DealDetailsFragment(), "dealDetailsFragment"); \t transaction.commit(); К сожалению, это приводит к возникновению Java.lang.ClassCastException: android.view.View не может быть передан в android.view.ViewGroup – bencallis

+0

Я отсортировал это исключение литья, используя LinearLayout, а не View. Приложение теперь запускается, но при нажатии «перейти» к сделкам URL-адрес не может быть загружен, так как webView по-прежнему равен нулю. – bencallis

7

EDIT: Я играл с этим некоторое время, и кажется, что WVF немного мусор и предназначен для переопределения. Однако об этом вообще нет документации! Проблема связана с тем, что вы можете вызвать getWebView() до загрузки изображения Fragment, следовательно, ваш NullPointerException. Кроме того, нет никакого способа обнаружить, когда представление Фрагмента было загружено, так что вы застряли!

Вместо этого я перепробовал класс, добавляя биты и меняя биты, чтобы теперь он работал нормально. Проверьте код this link. Тогда вместо того, чтобы использовать:

WebViewFragment webViewFragment = new WebViewFragment(); 

, чтобы загрузить фрагмент, используйте:

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

Этот класс также включает в себя удобный метод для загрузки URL, что не будет бросить Exception если есть нет WebView.

Итак, нет, я не думаю, что есть простой способ использовать встроенный WebViewFragment, но довольно легко сделать что-то, что работает вместо этого. Надеюсь, поможет!

+0

Я использую встроенный Android WebViewFragment [link] http://developer.android.com/reference/android/webkit/WebViewFragment.html. Я могу задуматься над тем, чтобы сделать свой собственный, но, безусловно, я должен быть в состоянии построить его. – bencallis

+0

О, да, извините, не осознал этого. У меня будет скрипка с кодом, который вы опубликовали, и посмотрим, смогу ли я помочь. –

+0

Спасибо. Вам повезло? – bencallis

3

WebViewFragment как это не так просто использовать. Попробуйте это простое расширение (Вы можете скопировать/вставить):

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