监听Fragment返回键事件,两种方法的区别

百度了一下找到了两种方法,并做了一下试验,发现两种方法的效果是不一样的。
(大家不试验一下也许就没有发现)

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代表返回事件指定我们指定的代码后,仍然执行默认的事件(默认的事件就是返回上一个页面)
效果图:

监听Fragment返回键事件,两种方法的区别_第1张图片
return true.png
监听Fragment返回键事件,两种方法的区别_第2张图片
return false

问题来了:让主界面获取焦点,那万一界面有EditText等控件抢了焦点呢?
那焦点就不在界面上了,按“返回键”后无法执行OnKeyListener中指定的代码。虽然有人提出了解决的方法,不过还是觉得考虑的情况不够全面。于是我决定使用第二种方法

监听Fragment返回键事件,两种方法的区别_第3张图片
未点击EditText前按返回键
监听Fragment返回键事件,两种方法的区别_第4张图片
编辑了EditText后按返回键,这是上一个页面

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 所以不会返回上一个页面,方便我截图
    }
}
监听Fragment返回键事件,两种方法的区别_第5张图片
就算编辑了EditText,返回键事件还是能监听

总结

第一种方法如果是在简单的页面就可以简单的实现监听返回键事件,
第二种方法就可以在比较复杂,有可能会抢焦点的页面用会好一点。

参考资料:(感谢大神的贡献)

优雅的让Fragment监听返回键
http://stackoverflow.com/questions/22552958/handling-back-press-when-using-fragments-in-android


好好学习,天天向上。<( ̄oo, ̄)/


监听Fragment返回键事件,两种方法的区别_第6张图片
Potato_zero.jpg

你可能感兴趣的:(监听Fragment返回键事件,两种方法的区别)