百度了一下找到了两种方法,并做了一下试验,发现两种方法的效果是不一样的。
(大家不试验一下也许就没有发现)
1. 在Fragment中onResume监听返回键事件
@Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if(keyEvent.getAction() == KeyEvent.ACTION_DOWN && i == KeyEvent.KEYCODE_BACK){
Toast.makeText(getActivity(), "按了返回键", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
});
}
setFocusableInTouchMode(true)和requestFocus()是让主界面获取焦点
这两行是很关键的,如果没有这两行,OnKeyListener的事件无法监听。
如果OnKeyListener中return true代表返回事件只执行我们指定的代码;
如果OnKeyListener中return false代表返回事件指定我们指定的代码后,仍然执行默认的事件(默认的事件就是返回上一个页面)
效果图:
image image问题来了:让主界面获取焦点,那万一界面有EditText等控件抢了焦点呢?
那焦点就不在界面上了,按“返回键”后无法执行OnKeyListener中指定的代码。虽然有人提出了解决的方法,不过还是觉得考虑的情况不够全面。于是我决定使用第二种方法
2. 优雅的方法
①先定义接口BackHandleInterface
public interface BackHandleInterface {
void onSelectedFragment(BackHandleFragment backHandleFragment);
}
②定义公用的Fragment
public abstract class BackHandleFragment extends Fragment {
private BackHandleInterface backHandleInterface;
/**
* 所有继承BackHandledFragment的子类都将在这个方法中实现物理Back键按下后的逻辑
* FragmentActivity捕捉到物理返回键点击事件后会首先询问Fragment是否消费该事件
* 如果没有Fragment消息时FragmentActivity自己才会消费该事件
*/
public abstract boolean onBackPressed();
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getActivity() instanceof BackHandleInterface){
this.backHandleInterface = (BackHandleInterface)getActivity();
}else{
throw new ClassCastException("Hosting Activity must implement BackHandledInterface");
}
}
@Override
public void onStart() {
super.onStart();
backHandleInterface.onSelectedFragment(this);
}
}
③需要实现监听的Fragment的Activity实现接口
主要的是onSelectedFragment()和onBackPressed()其他方法可以忽略
public class EdittextActivity extends AppCompatActivity implements BackHandleInterface {
private BackHandleFragment backHandleFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
addFragment(R.id.fragmentContainer, new EdittextFragment());
}
public void addFragment(int containerViewId, Fragment fragment){
final FragmentTransaction transaction = this.getSupportFragmentManager().beginTransaction();
transaction.add(containerViewId, fragment);
transaction.commit();
}
@Override
public void onSelectedFragment(BackHandleFragment backHandleFragment) {
this.backHandleFragment = backHandleFragment;
}
@Override
public void onBackPressed() {
//if判断里面就调用了来自Fragment的onBackPressed()
//一样!!,如果onBackPressed是返回false,就会进入条件内进行默认的操作
if(backHandleFragment == null || !backHandleFragment.onBackPressed()){
if(getSupportFragmentManager().getBackStackEntryCount() == 0){
super.onBackPressed();
}else{
getSupportFragmentManager().popBackStack();
}
}
}
}
④需要监听的Fragment
public class EdittextFragment extends BackHandleFragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_edittext, container, false);
return view;
}
@Override
public boolean onBackPressed() {
Toast.makeText(getActivity(), "按了返回键", Toast.LENGTH_SHORT).show();
return true;//因为这里return true 所以不会返回上一个页面,方便我截图
}
}
image
总结
第一种方法如果是在简单的页面就可以简单的实现监听返回键事件,
第二种方法就可以在比较复杂,有可能会抢焦点的页面用会好一点。
参考资料:(感谢大神的贡献)
优雅的让Fragment监听返回键
http://stackoverflow.com/questions/22552958/handling-back-press-when-using-fragments-in-android
作者:欢乐的乐
链接:https://www.jianshu.com/p/6e31ff8161c2
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
网友评论