Android按键监听(Dialog、Activity)优先级问题

KeyEvent类

Android.View.KeyEvent类中定义了一系列的常量和方法,用来描述Android中的按键事件。 和返回键有关的常量和方法有:java

  • KeyEvent.KEYCODE_BACK: 表示key类型为返回键
  • KeyEvent.ACTION_DOWN:表示事件为按下key,若是一直按住不放,则会不停产生此事件。
  • KeyEvent.ACTION_UP:表示事件为为放开key,一次点击key过程只会调用一次。
  • public final int getKeyCode():获取此事件对应的key类型。
  • public final int getAction():获取此事件对应的事件类型

Activity中拦截返回键

在Activity的派生类中能够经过重写onKeyDown和onKeyUp这两个方法来拦截返回键。ide

public boolean onKeyDown(int keyCode, KeyEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);
复制代码

这两个方法都有两个参数,第一个参数为keyCode,即此事件对应的key类型。第二个参数为此事件对象, 经过event能够获取到事件的详细信息。onKeyDown()方法中event.getAction()返回的始终是KeyEvent.ACTION_DOWNonKeyUp()方法中event.getAction()返回的始终是KeyEvent.ACTION_UP。 若是要拦截返回键,则在两个方法中加入以下代码。函数

if (keyCode == KeyEvent.KEYCODE_BACK) {
    ...
}
复制代码

Dialog中拦截返回键

在Dialog中能够经过调用setOnKeyListener()方法来为Dialog增长按键事件的监听。 setOnKeyListener()方法原型为:布局

public void setOnKeyListener(final OnKeyListener onKeyListener);spa

此方法有一个参数,参数须要实现OnKeyListener接口。OnKeyListener接口定义以下。code

interface OnKeyListener {
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event);
}
复制代码

onKey()方法包含三个参数,第一个参数是拦截到此事件的对话框对象的引用。第二个参数是此事件对应的keyCode,第三个参数是此事件对象自己。 若是要拦截返回键,则在Dialog中加入以下代码。对象

setOnKeyListener(new OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK 
            && event.getAction() == KeyEvent.ACTION_UP) {
            ...
        }
        return false;
    }
});
复制代码

EditText中拦截返回键事件

在EditText中一样能够经过调用setOnKeyListener()方法来为EditText增长按键事件的监听。 setOnKeyListener()方法的使用和Dialog中彻底相同。接口

View中拦截返回键事件

在全部View的派生类对象上均可以调用setOnKeyListener()方法来增长按键事件的监听,不过除了EditText以外,其余View设置了监听并不会起到做用。按键事件产生时并不会分发到View上。事件

多个拦截事件的冲突与选择

目前在Activity,Dialog和EditText中均可以成功设置拦截事件。若是多个对象设置了拦截事件。则事件只会分发到一个对象上。 经过实验获得以下结论: 一、Dialog优先级最高,若是有一个Activity,Activity中弹出一个Dialog,Dialog中有一个EditText,在Activity,Dialog和EditText中都设置监听,只有Dialog中设置的监听过程可以正确执行。Activity和EditText中的监听过程没法被执行到。 二、Activity优先级次于Dialog,但高于EditText,若是有一个Activity,Activity中有一个EditText,在Activity和EditText中都设置监听,只有Activity中设置的监听过程可以正确执行。EditText中的监听过程没法被执行到。 三、若是当前界面中有PopupWindow,则按返回键后PopupWindow会收到事件通知,并消费(执行dismiss();)。其余设置了监听的对象没法获取到事件通知。(缘由是PopupWindow内部布局类PopupViewContainer重写了dispatchKeyEvent()方法)get

返回键响应速度限制

当用户在按返回键后,若是界面出现卡顿,致使界面没有马上完成返回动做,这时用户可能以为是按下操做没有成功,又再一次按下返回键。这会致使返回事件又一次被调用。当卡顿结束后就出现屡次返回的现象。为了不这种状况出现,能够在拦截返回键的函数中增长时间限制。即若是本次返回事件距离上次处理时间过段,则不处理本次事件。直接return true;消费这次事件。 以对话框中拦截返回键举例,增长返回键响应速度限制的代码以下。

setOnKeyListener(new OnKeyListener() {
    private static final int INTERVAL = 500;   //响应间隔时间
    private long lastReturnTime;               //上次响应返回事件时间
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK 
            && event.getAction() == KeyEvent.ACTION_UP) {
            long curTime = System.currentTimeMillis();
            if (curTime - lastReturnTime > INTERVAL) {
                lastReturnTime = curTime;
                ...
            } else {
                return true;
            }
        }
        return false;
    }
});
复制代码
相关文章
相关标签/搜索