执行 FragmentTransaction 后 WebViewFragment webView 为 null

发布于 2025-01-03 02:12:42 字数 2154 浏览 2 评论 0原文

目前,我的应用程序设置为左侧有一个 ListFragment ,右侧有一个 DetailsFragment (类似于下面平板电脑上的布局)。

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: 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 的信息很少。

有什么想法如何确保在 WebViewFragment 中初始化 WebView 吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青巷忧颜 2025-01-10 02:12:43

在 Espiandev 的大力帮助下,我成功获得了一个可以工作的 WebView。为了确保链接在片段中打开,而不是在 Web 浏览器应用程序中打开,我创建了一个简单的 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;
        }


    }

希望这对将来的人有用。

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.

遗心遗梦遗幸福 2025-01-10 02:12:43

编辑:所以我玩了一段时间,看起来 WVF 有点垃圾,而且设计得可以被覆盖。然而,根本没有这方面的文档!问题源于这样一个事实:您可以在加载 Fragment 视图之前调用 getWebView(),因此会出现 NullPointerException。除了没有任何方法可以检测 Fragment 的视图何时加载,所以你有点卡住了!

相反,我重写了该类,添加了位并更改了位,这样现在它就可以正常工作了。
检查此链接获取代码。然后,不要使用:

WebViewFragment webViewFragment = new WebViewFragment();

来加载您的片段,而是使用:

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

此类还包含一个用于加载网址的便捷方法,如果没有,该方法不会抛出异常 >WebView

所以,不,我不认为有一种特别简单的方法来使用内置的 WebViewFragment,但是制作一些可以工作的东西是相当容易的。希望有帮助!

EDIT: So I played around with this for a while and it seems that the WVF is a bit rubbish and designed to be overridden. However, there's no documentation on this at all! The problem stems from the fact you can call getWebView() before the Fragments view is loaded, hence your NullPointerException. Except there isn't any way to detect when the Fragment's view has been loaded, so you're kind of stuck!

Instead I overrode the class, adding bits and changing bits, so that now it will work fine.
Check this link for the code. Then instead of using:

WebViewFragment webViewFragment = new WebViewFragment();

to load your Fragment, use:

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

This class also includes a convenience method for loading a url, that won't throw an Exception if there's no WebView.

So, no, I don't think there's a particularly simple way for using the built-in WebViewFragment, but it is pretty easy to make something that works instead. Hope it helps!

梦在夏天 2025-01-10 02:12:43

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

WebViewFragment as is is not that straightforward to use. Try this simple extension (You can copy/paste):

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

Call where you need using the factory method:

WebViewFragment fragment = UrlWebViewFragment.newInstance("http://ur-url.com");
御守 2025-01-10 02:12:43

仅当片段是用 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

现在,您问题中的交易应该可以正常工作。 :)

Fragments can only be replaced if they were initiallized in Java, not XML. I think so, I had the same problem and it solved it. Change your XML to this:

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

and then in Java, your onCreate method:

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

or even better create whole method to just deal with Transactions.

Now Transaction from your question should work. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文