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;
    }
});
複製代碼
相關文章
相關標籤/搜索