最近在做一个小项目,涉及到软键盘,故而记录下回退出去需要执行的操作,也是比较一下以上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()
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()方法,其他的方法得不到执行。