onBackPressed()、onKeyDown()和dispatchKeyEvent()与有无软键盘的差异

    最近在做一个小项目,涉及到软键盘,故而记录下回退出去需要执行的操作,也是比较一下以上3个方法,不至于混淆

dispatchKeyEvent(KeyEvent event) 可以类比View里面的dispatchTouchEvent() 该方法会在摁下和抬起过程中进行调用,必然会调用该方法

onKeyDow() 在摁下返回键的时候进行调用,前提是 dispatchKeyEvent()调遣并传递到该事件上了

onBackPressed() 的优先级是最低的,只有执行了onKeyDown()且返回false,那么该方法才会得到执行

diapatchEvent()源码如下,

    @Override
    boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
            // If this is a MENU event, let the Activity have a go.
            if (mOriginalWindowCallback.dispatchKeyEvent(event)) {
                return true;
            }
        }

        final int keyCode = event.getKeyCode();
        final int action = event.getAction();
        final boolean isDown = action == KeyEvent.ACTION_DOWN;

        return isDown ? onKeyDown(keyCode, event) : onKeyUp(keyCode, event);
    }


1 默认情况下,即直接继承时:

    @Override
    public void onBackPressed() {
        LogUtils.e("摁返回键","onBackPressed()调用了");
        super.onBackPressed();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        LogUtils.e("摁返回键","onKeyDown调用了");
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        LogUtils.e("摁返回键","dispatchKeyEvent调用了");
        return super.dispatchKeyEvent(event);
    }

1.1 无软键盘 单击返回按钮:在按下和抬起时执行 dispatchTouchEvent(),完了执行keydown


1.2 有软键盘 单击返回按钮: 只执行了 dispatchEvent()


扫描二维码关注公众号,回复: 1832205 查看本文章

1.3 无软键盘 长按  抬起执行dispatchKeyEnent 和onBackPressed()


1.4 有软键盘 长按 不执行onBackPressed()


2. dispatchKeyEvent()  直接返回true or false 并不会派遣事件,onKeyDown()和onBackPressed()必然得不到执行,

源码中的方法: callback.dispatchKeyEnent(event)

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        LogUtils.e("摁返回键","dispatchKeyEvent调用了");
        return true;
    }
2.1 无软键盘 单击返回按钮


2.2 有软键盘 单击返回按钮 


2.3 有无软键盘长按事件

]

3. 有了以上的基础,判断下按下返回按钮的情况

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_MENU){
            LogUtils.e("摁返回键","为true 调遣 直接返回true");
        }else {
            LogUtils.e("摁返回键","为false 调遣 再传递 返回false ");
        }
        LogUtils.e("摁返回键","dispatchKeyEvent调用了");
        return super.dispatchKeyEvent(event);
    }

无软键盘时:


有软键盘时:


从以上结果可以看出当有软键盘时按下时,并不会调用dispatchKeyEvent()而抬起时才会执行

然后我又去看了EditText的父类源码:

    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
            // special case for the back key, we do not even try to send it
            // to the drop down list but instead, consume it immediately
            final View anchorView = mDropDownAnchorView;
            if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
                if (state != null) {
                    state.startTracking(event, this);
                }
                return true;
            } else if (event.getAction() == KeyEvent.ACTION_UP) {
                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
                if (state != null) {
                    state.handleUpEvent(event);
                }
                if (event.isTracking() && !event.isCanceled()) {
                    dismiss();
                    return true;
                }
            }
        }
        return false;
    }
发现软件盘在isShowing按下的时候,是返回true的消费事件的,而只有抬起的时候,该方法还会再次调用,这时候返回false进行调用了,然后就会有dispatchkeyEvent()事件的传递了。


结论: 对于弹出软键盘的情况,这时候按下返回按钮,被onKeyPreime()消费了,那么只会在抬起的时候执行 dispatchKeyEvent()方法,其他的方法得不到执行。

猜你喜欢

转载自blog.csdn.net/crazyzhangxl/article/details/80184767
今日推荐