Activity中的有的Fragment由FragmentManager管理,Fragment嵌套的子Fragment也由FragmentManager处理,那只要拿到FragmentManager就可以用递归的方式处理了
1、同样的先定义一个FragmentBackHandler 接口。
public interface FragmentBackHandler {
boolean onBackPressed();
}
2、定义一个BackHandlerHelper工具类,用于实现分发back事件,Fragment和Activity的外理逻辑是一样,所以两者都需要调用该类的方法。
public class BackHandlerHelper {
/**
* 将back事件分发给 FragmentManager 中管理的子Fragment,如果该 FragmentManager 中的所有Fragment都
* 没有处理back事件,则尝试 FragmentManager.popBackStack()
*
* @return 如果处理了back键则返回 <b>true</b>
* @see #handleBackPress(Fragment)
* @see #handleBackPress(FragmentActivity)
*/
public static boolean handleBackPress(FragmentManager fragmentManager) {
List<Fragment> fragments = fragmentManager.getFragments();
if (fragments == null) return false;
for (int i = fragments.size() - 1; i >= 0; i--) {
Fragment child = fragments.get(i);
if (isFragmentBackHandled(child)) {
return true;
}
}
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
return true;
}
return false;
}
public static boolean handleBackPress(Fragment fragment) {
return handleBackPress(fragment.getChildFragmentManager());
}
public static boolean handleBackPress(FragmentActivity fragmentActivity) {
return handleBackPress(fragmentActivity.getSupportFragmentManager());
}
/**
* 判断Fragment是否处理了Back键
*
* @return 如果处理了back键则返回 <b>true</b>
*/
public static boolean isFragmentBackHandled(Fragment fragment) {
return fragment != null
&& fragment.isVisible()
&& fragment.getUserVisibleHint() //for ViewPager
&& fragment instanceof FragmentBackHandler
&& ((FragmentBackHandler) fragment).onBackPressed();
}
}
3、当然 Fragment 也要实现 FragmentBackHandler接口(按需)
//没有处理back键需求的Fragment不用实现
public abstract class BackHandledFragment extends Fragment implements FragmentBackHandler {
@Override
public boolean onBackPressed() {
return BackHandlerHelper.handleBackPress(this);
}
}
4、Activity覆盖onBackPressed方法(必须)
public class MyActivity extends FragmentActivity {
//.....
@Override
public void onBackPressed() {
if (!BackHandlerHelper.handleBackPress(this)) {
super.onBackPressed();
}
}
}
不是说好的两步么,这TM是4步啊!大哥不要生气,第一步和第二步我都给你做了,你只要在Gradle中加入以下的话以及第3、4步即可。你可以使用我提供的BackHandledFragment也可以让自己的BaseFragment实现FragmentBackHandler接口(只在需要Fragmen中实现就行),并在onBackPressed中用填入return BackHandlerHelper.handleBackPressed(this);。
@Override
public boolean onBackPressed() {
// 当确认没有子Fragmnt时可以直接return false
if (backHandled) {
Toast.makeText(getActivity(), toastText, Toast.LENGTH_SHORT).show();
return true;
} else {
return BackHandlerHelper.handleBackPress(this);
}
BackHandledFragment 或其它实现了 FragmentBackHandler的Fragment。
back事件由下往上传递,当中间有未实现FragmentBackHandler的Fragment作为其它Fragment的容器时,或该Fragment拦截了事件时,其子Fragment无法处理back事件。
有没有一种似曾相识的感觉?其实这和View的事件分发机制是一个道理。
原理
1、不管是Activity也好,Fragment也好,其中内部包含的Fragment都是通过FragmentManager来管理的。
2、FragmentManager.getFragments()可以获取当前Fragment/Activity中处于活动状态的所有Fragment
3、事件由Activity交给当前Fragment处理,如果Fragment有子Fragment的情况同样可以处理。
这么做的好处
1、Activity不必实现接口,仅需在onBackPressed中调用BackHandlerHelper.handleBackPress(this)即可,Fragment同理。
2、支持多个Fragment
3、支持Fragment嵌套
4、改动小,只修改有拦截back键需求的Fragment及其父Fragment,其它可以不动。