【问题标题】:How to add "Go Back" function in WebView inside Fragment?如何在 Fragment 内的 WebView 中添加“返回”功能?
【发布时间】:2012-05-17 07:14:43
【问题描述】:

更新:已解决!问题与我的 Viewpager 而不是 WebView 有关。

我正在尝试向我的WebView 添加一个“返回”功能,该功能位于Fragment 内。但我不知道如何:

public final class TestFragment extends Fragment {

    static WebView mWeb;
    private View mContentView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {   
        mContentView = inflater.inflate(R.layout.webview, null);
        mWeb = (WebView)mContentView.findViewById(R.id.webview);

        WebSettings settings = mWeb.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setSupportZoom(false);
        mWeb.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        mWeb.getSettings().setBuiltInZoomControls(false);
        mWeb.loadUrl("myurl...");
        mWeb.setOnKeyListener(new OnKeyListener(){
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
                    mWeb.goBack();
                    return true;
                }
                return false;
            }
        });
    }   
}

我也尝试过类似的方法:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
        mWeb.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

另一个解决方案但同样的问题:

@Override
public void onBackPressed()
{
    if(webView.canGoBack())
        webView.goBack();
    else
        super.onBackPressed();
}

任何想法如何让它工作?

【问题讨论】:

标签: android android-fragments android-webview


【解决方案1】:

也许是它的 android 限制。尝试使用处理程序执行此操作。

public final class TestFragment extends Fragment {


    static WebView mWeb;
    private View mContentView;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case 1:{
                    webViewGoBack();
                }break;
            }
        }
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {   

        mContentView = inflater.inflate(R.layout.webview, null);
        mWeb = (WebView)mContentView.findViewById(R.id.webview);

        WebSettings settings = mWeb.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setSupportZoom(false);
        mWeb.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        mWeb.getSettings().setBuiltInZoomControls(false);
        mWeb.loadUrl("myurl...");
        mWeb.setOnKeyListener(new OnKeyListener(){

            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK 
                        && event.getAction() == MotionEvent.ACTION_UP 
                        && mWeb.canGoBack()) {
                    handler.sendEmptyMessage(1);
                    return true;
                }

                return false;
            }

        });

    }   

    private void webViewGoBack(){
        mWeb.goBack();
    }
}

【讨论】:

  • 也为我工作,这应该被选为答案!
  • 这行得通,但是有一个缺陷。您只检测到 keyCode,而不是 KeyEvent。因此,当您按下返回按钮时,您的 onKey 将被调用两次,一次用于按下,一次用于向上。所以应该是: if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == MotionEvent.ACTION_UP) {
  • 你能告诉我为什么使用 handler.without handler 是不可能的
【解决方案2】:

您可以检查此代码:

    webView.canGoBack();
    webView.setOnKeyListener(new View.OnKeyListener() {

        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK
                    && event.getAction() == MotionEvent.ACTION_UP
                    && webView.canGoBack()) {
                webView.goBack();
                return true;
            }
            return false;
        }
    });

【讨论】:

    【解决方案3】:

    其实你不能直接在fragment里面做。 onBackPressed 可以在 FragmentActivity 中被覆盖。你可以做的是:

    1. 覆盖活动中的onBackPressed
    2. 调用onBackPressed时,检查当前fragment的实例是否为显示webview的实例。
    3. 如果是,请询问fragment webview 是否可以返回。
    4. 如果不是,请拨打super 或任何您需要的电话

    编辑:

     @Override
     public void onBackPressed() {
           Fragment webview = getSupportFragmentManager().findFragmentByTag("webview");
           if (webview instanceof MyWebViewFragment) {
                  boolean goback = ((MyWebViewFragment)webview).canGoBack();
                  if (!goback)
                    super.onBackPressed();
           }
     }
    

    【讨论】:

    • 感谢这段代码,真的帮助我快速解决了我在使用导航抽屉和片段 webview 时遇到的问题。
    【解决方案4】:

    我创建了一个简单的界面:

    public interface IOnBackPressed {
        boolean onBackPressed();
    }
    

    在活动中:

    public class MyActivity extends Activity {
        @Override public void onBackPressed() {
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
           if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
              super.onBackPressed();
           }
        }
    }
    

    在片段中:

    public class MyFragment extends Fragment implements IOnBackPressed {
       @Override
        public boolean onBackPressed() {
            if (webview.canGoBack()) {
                webview.goBack();
                // backpress is not considered in the Activity
                return true;
            } else {
                // activity will act normal
                return false;
            }
        }
    }
    

    【讨论】:

    • 非常完美!
    【解决方案5】:

    WebViewActivity.java,我添加了1个方法:

    @Override
    public void onBackPressed() {
    
        WebViewFragment fragment = (WebViewFragment)
                getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
        if (fragment.canGoBack()) {
            fragment.goBack();
        } else {
            super.onBackPressed();
        }
    }
    

    WebViewFragment.java,我添加了2个方法:

    public boolean canGoBack() {
        return mWebView.canGoBack();
    }
    
    public void goBack() {
        mWebView.goBack();
    }
    

    【讨论】:

      【解决方案6】:

      @RomanBlack 的回答给了我正确的想法,但由于我们使用 kotlin,我不得不稍微调整一下答案。

      webView.setOnKeyListener { _, _, keyEvent ->
              if (keyEvent.keyCode == KeyEvent.KEYCODE_BACK && !webView.canGoBack()) {
                  false
              } else if (keyEvent.keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == MotionEvent.ACTION_UP) {
                  webView.goBack()
                  true
              } else true
          }
      

      如果你想通过退货来做到这一点,你必须添加如下内容:

      return@setOnKeyListener true
      

      【讨论】:

        【解决方案7】:

        BackPressedDispatcher 有一个简单的方法

        片段:

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val callback = object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    if(webView.canGoBack()){
                       webView.goBack()
                    } else {
                        isEnabled = false
                        requireActivity().onBackPressed()
                    }
                }
            }
            requireActivity().onBackPressedDispatcher.addCallback(this,callback)
        }
        

        活动:

        override fun onBackPressed() {
            val fragment = supportFragmentManager.findFragmentByTag("WebViewFragment")
            if (WebViewFragment::class.java.isInstance(fragment)) {
                if (onBackPressedDispatcher.hasEnabledCallbacks()) {
                    onBackPressedDispatcher.onBackPressed()
                    return
                }
                super.onBackPressed()
            }
        }
        

        也许这些代码可以改进,但对我来说效果很好。欲了解更多信息,请访问here

        【讨论】:

          【解决方案8】:

          我的解决方案在我添加到公共方法的片段中

          public static boolean canGoBack(){
                  return mWebView.canGoBack();
              }
          
              public static void goBack(){
                  mWebView.goBack();
              }
          

          然后从我调用的活动中

          @Override
          public void onBackPressed() {
              if(webFragment.canGoBack()){
                  webFragment.goBack();
              }else{
                  super.onBackPressed();
              }
          
          }
          

          注意 mwebview 是静态的

          【讨论】:

            【解决方案9】:

            你可以这样做:

            • Activity 中放:

              // Set WebView
              
              public void setWebView(WebView web) {
              
                  this.web = web;
              }
              
            • ActivityCreated()之后的网页片段中放:

              ((Your_Activity) getActivity()).setWebView(webView);

            • 不要忘记从onCreateView() 设置webView,如下所示:

              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container,
                      Bundle savedInstanceState) {
                  webView = (WebView) inflater.inflate(R.layout.your_web_fragment, container,
                          false);
                  return web;
              }
              

            【讨论】:

              【解决方案10】:

              @OmidAmnivia 的答案是正确的,您的应用程序崩溃的解决方案是

              @Override
              public void onBackPressed() {
              if(webFragment.isInitialized && webFragment.canGoBack()){
                  webFragment.goBack();
              }else{
                  super.onBackPressed();
              }
              }
              

              你必须检查你的类是否已经初始化。

              【讨论】:

                【解决方案11】:

                这就是我在我的应用程序中所做的。我消费后按事件,直到 web 视图可以返回。一旦网络视图无法返回,我会向用户显示提示,如果他继续按下,则应用程序将退出。

                当 webview 无法返回时,它会让用户有机会留在您的应用中。我觉得它对用户更友好:

                          //time passed between two back presses.
                          private val TIME_INTERVAL = 200 
                           // variable to keep track of last back press
                          private var mBackPressed: Long = 0
                
                
                        webView!!.requestFocus()
                        webView.setOnKeyListener(View.OnKeyListener { v, keyCode, event ->
                            if (keyCode == KeyEvent.KEYCODE_BACK
                                    && event.action == MotionEvent.ACTION_UP
                                  ) {
                                if(webView.canGoBack()) {
                                    //go back in previous page
                                    webView.goBack()
                                    return@OnKeyListener true
                                }
                                else
                                {
                                    if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis())
                                    {   // dont consume back press and pass to super
                                        return@OnKeyListener false
                                    }
                                    else {
                                        // show hint for double back press
                                        Toast.makeText(context, " Double Tap back button to exit the demo", Toast.LENGTH_SHORT).show();
                                        mBackPressed = System.currentTimeMillis();
                                        return@OnKeyListener true
                                    }
                                }
                            }
                            return@OnKeyListener false
                
                        })
                

                【讨论】:

                  【解决方案12】:

                  首先在片段中返回按下

                   mContentView.setFocusableInTouchMode(true);
                   mContentView.requestFocus();
                   mContentView.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;
                    }
                   } );
                  

                  希望它会起作用。

                  【讨论】:

                    【解决方案13】:

                    这在我的情况下有效

                    public class FantasyFragment extends Fragment  implements SwipeRefreshLayout.OnRefreshListener {
                    
                    WebView webview;
                    SwipeRefreshLayout swipeLayout;
                    String currentUrl="https://www.stackoverflow.com/";
                    
                    @Override
                    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                             Bundle savedInstanceState) {
                        // Inflate the layout for this fragment
                        View root = inflater.inflate(R.layout.fragment_stadium, container, false);
                    
                    
                        swipeLayout = (SwipeRefreshLayout) root.findViewById(R.id.swipescreen);
                        swipeLayout.setOnRefreshListener(this);
                    
                        return root;
                    }
                    
                    @Override
                    public void onStart() {
                        super.onStart();
                        LoadWeb();
                    }
                    
                    public void LoadWeb() {
                    
                    
                    
                        webview = (WebView) getActivity().findViewById(R.id.webview786);
                        swipeLayout.setRefreshing(true);
                        webview.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
                        webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
                        webview.getSettings().setAppCacheEnabled(true);
                    
                        WebSettings webSettings = webview.getSettings();
                        webSettings.setJavaScriptEnabled(true);
                    
                        webSettings.setDatabaseEnabled(true);
                        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
                        webSettings.setUseWideViewPort(true);
                        webSettings.setSavePassword(true);
                        webSettings.setSaveFormData(true);
                        webSettings.setEnableSmoothTransition(true);
                    
                        webview.loadUrl(currentUrl);
                    
                        webview.setWebViewClient(new WebViewClient() {
                            @Override
                            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                                Snackbar.make(view, "Connection Error", Snackbar.LENGTH_LONG)
                                        .setAction("Retry", new View.OnClickListener() {
                                            @Override
                                            public void onClick(View v) {
                                                LoadWeb();
                                            }
                                        }).show();
                            }
                            @Override
                            public void onPageFinished(WebView view, String url) {
                                swipeLayout.setRefreshing(false);
                                currentUrl = url;
                                super.onPageFinished(view, url);
                            }
                        });
                    
                        webview.canGoBack();
                        webview.setOnKeyListener(new View.OnKeyListener() {
                    
                            public boolean onKey(View v, int keyCode, KeyEvent event) {
                                if (keyCode == KeyEvent.KEYCODE_BACK
                                        && event.getAction() == MotionEvent.ACTION_UP
                                        && webview.canGoBack()) {
                                    webview.goBack();
                                    return true;
                                }
                                return false;
                            }
                        });
                    }
                    @Override
                    public void onRefresh() {
                        LoadWeb();
                    }
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      最简单的答案是将setOnKeyListeneron 插入 webView 本身:

                      webView.setOnKeyListener(new View.OnKeyListener() {
                          @Override
                          public boolean onKey( View v, int keyCode, KeyEvent event ) {
                              if (event.getAction() == KeyEvent.ACTION_DOWN) {
                                  if( keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()){
                                      webView.goBack();
                                      return true;
                                  }
                              }
                              return false;
                          }
                      });
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2022-01-12
                        • 2014-04-24
                        • 1970-01-01
                        • 2023-04-10
                        • 1970-01-01
                        • 2016-05-05
                        • 2016-08-16
                        • 2022-01-03
                        相关资源
                        最近更新 更多