本文章主要講解怎么解決在Activity中,彈出Dialog后無法捕捉到Activity的Back點(diǎn)擊事件。
通常,我們捕捉Back點(diǎn)擊事件一般有以下幾種方法:
重寫onKeyDown或者onKeyUp方法
重寫onBackPressed方法
重寫dispatchKeyEvent方法
但是當(dāng)在有Dialog彈出時,想捕捉Back鍵的事件的話,上述三種辦法都無法實(shí)現(xiàn)。原因是Dialog在Activity中彈出,因此Dialog搶走了Activity的焦點(diǎn),當(dāng)前的焦點(diǎn)變?yōu)镈ialog了,所以Activity不是當(dāng)前焦點(diǎn),因此無法獲取到Back鍵事件。也就是說只有當(dāng)Activity是當(dāng)前焦點(diǎn)時,它才可以捕捉到相應(yīng)的Back鍵事件,而有Dialog彈出時,Dialog獲取了當(dāng)前焦點(diǎn)。但是如果我們需要做到相應(yīng)的需求時,此時有兩種思路可以解決這個問題:
Dialog中攔截返回鍵
- 一 ) 在Dialog中可以通過調(diào)用setOnKeyListener()方法來為Dialog增加按鍵事件的監(jiān)聽。并重寫dispatchKeyEvent方法。
//設(shè)置Dialog中的setOnKeyListener
selectDialog.setOnKeyListener(new OnKeyListener() {
//第一個參數(shù)是攔截到此事件的對話框?qū)ο蟮囊?第二個參數(shù)是此事件對應(yīng)的keyCode,第三個參數(shù)是此事件對象本身。
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()==0)
{
dialog.dismiss();
}
return false;
}
});
//然后在dispatchKeyEvent里面就可以實(shí)現(xiàn)自己想要實(shí)現(xiàn)的操作了。
public boolean dispatchKeyEvent(KeyEvent event)
{
switch(event.getKeyCode())
{
case KeyEvent.KEYCODE_BACK:
Toast.makeText(getBaseContext(), "點(diǎn)擊了back", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
return super.dispatchKeyEvent(event);
}
- 二 ) 在Dialog中可以通過設(shè)置Dialog的setOnCancelListener。
//這樣就可以捕捉到Back鍵的事件了,當(dāng)按下Back鍵時,系統(tǒng)默認(rèn)的操作會讓Dialog cancel掉,此時會觸發(fā)OnCancelListener,然后在onCancel方法里面就可以實(shí)現(xiàn)自己想要實(shí)現(xiàn)的操作了。
selectDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// TODO Auto-generated method stub
dialog.dismiss();
//可以執(zhí)行你想要實(shí)現(xiàn)的操作,我遇到的需求是關(guān)閉當(dāng)前Activity
finish();
}
});
常用點(diǎn)擊事件
- KeyEvent.KEYCODE_BACK: 表示key類型為返回鍵
- KeyEvent.ACTION_DOWN:表示事件為按下key,如果一直按住不放,則會不停產(chǎn)生此事件
- KeyEvent.ACTION_UP:表示事件為放開key,一次點(diǎn)擊key過程只會調(diào)用一次
Activity攔截返回鍵
在Activity的派生類中可以通過重寫onKeyDown和onKeyUp這兩個方法來攔截返回鍵。
public boolean onKeyDown(int keyCode, KeyEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);
多個控件的攔截事件的處理
目前在Activity,Dialog和EditText中都可以成功設(shè)置攔截事件。如果多個對象設(shè)置了攔截事件。則事件只會分發(fā)到一個對象上。
通過實(shí)驗(yàn)得到如下結(jié)論:
1、Dialog優(yōu)先級最高,如果有一個Activity,Activity中彈出一個Dialog,Dialog中有一個EditText,在Activity,Dialog和EditText中都設(shè)置監(jiān)聽,只有Dialog中設(shè)置的監(jiān)聽過程能夠正確執(zhí)行。Activity和EditText中的監(jiān)聽過程無法被執(zhí)行到。
2、Activity優(yōu)先級次于Dialog,但高于EditText,如果有一個Activity,Activity中有一個EditText,在Activity和EditText中都設(shè)置監(jiān)聽,只有Activity中設(shè)置的監(jiān)聽過程能夠正確執(zhí)行。EditText中的監(jiān)聽過程無法被執(zhí)行到。
3、如果當(dāng)前界面中有PopupWindow,則按返回鍵后PopupWindow會收到事件通知,并消費(fèi)(執(zhí)行dismiss();)。其他設(shè)置了監(jiān)聽的對象無法獲取到事件通知。(原因是PopupWindow內(nèi)部布局類PopupViewContainer重寫了dispatchKeyEvent()方法)