Android 如何在 Fragment 内的 WebView 中添加“返回”功能?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10631425/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:25:57  来源:igfitidea点击:

How to add "Go Back" function in WebView inside Fragment?

androidandroid-fragmentsandroid-webview

提问by Markus Rubey

UPDATE: Solved! Problem was related to my Viewpager not WebView.

更新:解决了!问题与我的 Viewpager 而非 WebView 有关。

I'm trying to add a "Go Back" function to my WebViewwhich is inside a Fragment. But I can't figure out how to:

我正在尝试将“返回”功能添加到我WebViewFragment. 但我不知道如何:

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

I also tried something like:

我也尝试过类似的事情:

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

Another solution but same problem:

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

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

Any ideas how to get this working?

任何想法如何让这个工作?

回答by Roman Black

Perhaps its android restriction. Try to do this using handler.

也许它的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();
    }
}

回答by XZandr

You can check this code :

您可以检查此代码:

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

回答by Blackbelt

Actually you can not do directly inside the fragment. The onBackPressedcan be overridden in the FragmentActivity. What you can do is:

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

  1. Override the onBackPressedinside the activity.
  2. When the onBackPressedis called, check if the instance of the current fragment is the instance showing the webview.
  3. If it is, ask the fragmentif the webviewcan go back.
  4. if it is not, call the superor whatever you need
  1. 覆盖onBackPressed活动的内部。
  2. onBackPressed被调用时,检查当前片段的实例是否是显示webview.
  3. 如果是,请问fragment是否webview可以返回。
  4. 如果不是,请致电super或您需要的任何东西

Edit:

编辑:

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

回答by Ram Patra

In WebViewActivity.java, I added 1 method:

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

@Override
public void onBackPressed() {

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

In WebViewFragment.java, I added 2 methods:

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

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

public void goBack() {
    mWebView.goBack();
}

回答by Mike T

@RomanBlack's answer gave me the right idea, but since we use kotlin I had to adapt the answer a little bit.

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

if you want to do it with returns you have to add something like:

如果你想用退货来做,你必须添加如下内容:

return@setOnKeyListener true

回答by Omid Aminiva

my solution was in fragment I added to public methods

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

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

    public static void goBack(){
        mWebView.goBack();
    }

then from activity I call

然后从我打电话的活动中

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

}

note The mwebview is static

注意 mwebview 是静态的

回答by AndroMan

you can do this by :

你可以这样做:

  • in the Activityput :

    // Set WebView
    
    public void setWebView(WebView web) {
    
        this.web = web;
    }
    
  • in the web fragment after ActivityCreated()put:

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

  • Don't forget to set webViewfrom the onCreateView()like these:

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

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

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

  • 不要忘记webViewonCreateView()这些设置:

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

回答by Manuel Schmitzberger

I've created a simple interface:

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

public interface IOnBackPressed {
    boolean onBackPressed();
}

in the Activity:

在活动中:

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

in the Fragment:

在片段中:

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

回答by Hitesh Sahu

This is how I did in my app. I consume back press event till web view can go back. Once web view cant go back I show hint to user that if he keep on pressing back then app will exit.

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

It will give user a chance to stay in your app when webview cant go back. I felt it more user friendly:

当 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

        })

回答by h_code

@OmidAmnivia answer is correct your app the solution to the crash is

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

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

You have to check whether your class has been initialised or not.

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