WebViewFragment webView является нулевым после выполнения FragmentTransaction - PullRequest
12 голосов
/ 06 февраля 2012

В настоящее время мое приложение настроено с ListFragment слева и DetailsFragment справа (аналогично расположению на планшете ниже).

layout

На фрагменте сведений (фрагмент рядом со списком) у меня есть кнопка перехода к сделке, которая при нажатии должна заменить фрагмент подробностей на 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: 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>

Кажется, что webViewFragment не создается полностью, поскольку WebView не был инициализирован. Я посмотрел в Интернете, но очень мало информации о WebViewFragment.

Есть идеи, как обеспечить инициализацию WebView в WebViewFragment?

Ответы [ 4 ]

12 голосов
/ 09 февраля 2012

С большой помощью 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;
        }


    }

Надеюсь, это пригодится кому-то в будущем.

7 голосов
/ 08 февраля 2012

РЕДАКТИРОВАТЬ: Таким образом, я поэкспериментировал с этим некоторое время, и кажется, что WVF немного мусор и предназначен для переопределения. Тем не менее, нет никакой документации по этому вопросу вообще! Проблема связана с тем, что вы можете вызвать getWebView () до загрузки представления Fragment, следовательно, ваш NullPointerException. За исключением того, что нет никакого способа определить, когда представление фрагмента было загружено, так что вы застряли!

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

WebViewFragment webViewFragment = new WebViewFragment();

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

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

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

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

2 голосов
/ 26 октября 2014

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");
0 голосов
/ 06 февраля 2012

Фрагменты могут быть заменены, только если они были инициализированы в 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: layout=@layout/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 s.

Теперь Transaction от вашего вопроса должно работать. :)

...