1、前言

我使用Activity包含几个Fragment的应用模式来实现APP,APP应用也很简单,就是每个Fragment中使用一个WebView来封装H5页面即可,碰到的问题就是在H5页面中跳转时,如果需要回退,则会直接退出APP,但我要的是像正常浏览网页一样,回退到前页,在Activity中监听回退事件是件非常容易的事,因为直接重写onBackPressed()函数就好了,但当大家想要监听Fragment中的回退事件时,想当然的也想着重写onBackPressed()方法,这时候你会发现:Fragment中根本就没有onBackPressed()方法给你重写。那如何解决呢?

首先,回退事件总是发给Activity的!在发给Activity以后再由Activity自己处理。比如它将Fragment回退栈中的内容一个个出栈这种操作。

其次:大家要知道:Fragment只是Activity中的一个控件而已,虽然我们可能把他做成了像Activity一样大小覆盖整个页面,看起来跟Activity样子上没什么区别,但他还是个控件!系统不会给一个控件分发回退事件

2、解决方案

既然清楚了Fragment只是一个控件,而回退事件也只能在Activity中拦截。那我们就可以想办法了。
首先,我们可以在Fragment类中咱们自己写一个onBackPressed()方法来处理回调事件。
然后,可以利用回调,将要处理回退事件的fragment实例,传给Activity。
最后,在拿到fragment实例以后,就可以在Activity的onBackPress()方法中,调用这个fragment实例的onBackPressed()方法了。
这样,我们就在fragment中拦截了回退事件了。

下面看下具体的实现过程:
1、先定义2个接口,分别用在Activity和Fragment中,作为2者的沟通方法

public interface IActivityBackHandler {
void setSelectdFragment(IFragmentBackHandler pBackHandledFragment);
}
public interface IFragmentBackHandler {
boolean onBackPressed();
}

2、在Fragment中实现IFragmentBackHandler 并定义onBackPress()函数及处理:

public class HomeFragment extends Fragment implements IFragmentBackHandler {
@Override
public boolean onBackPressed(){
if(_webView.canGoBack()){
_webView.goBack();
return true;
}else{
return false;
}
}

3在MainActivity中实现IActivityBackHandler 并定义setSelectdFragment()函数及处理:

private IFragmentBackHandler _selectedFragment;

@Override
public void setSelectdFragment(IFragmentBackHandler pBackHandledFragment) {
this._selectedFragment = pBackHandledFragment;
}

4、在Activity拦截一下onBackPressed事件

@Override
public void onBackPressed(){
if(_selectedFragment == null || !_selectedFragment.onBackPressed()){
super.onBackPressed();
}
}

5在Fragement的onCreateView事件中,传递当前Framegment给Activity

if(!((getActivity()) instanceof IActivityBackHandler)){
throw new ClassCastException("Activity类型未实现接口IActivityBackHandler");
}else{
_backHandler = (IActivityBackHandler) getActivity();
_backHandler.setSelectdFragment(this);
}

大功告成!现在浏览网页可以正常回退了,直到没有回退路径时,才会执行退出APP的逻辑!