android Dialog在Activity中,如何处理Activity捕捉不到Back点击事件

本文章主要讲解怎么解决在Activity中,弹出Dialog后无法捕捉到Activity的Back点击事件。

通常,我们捕捉Back点击事件一般有以下几种方法:

  • 重写onKeyDown或者onKeyUp方法

  • 重写onBackPressed方法

  • 重写dispatchKeyEvent方法

但是当在有Dialog弹出时,想捕捉Back键的事件的话,上述三种办法都无法实现。原因是Dialog在Activity中弹出,因此Dialog抢走了Activity的焦点,当前的焦点变为Dialog了,所以Activity不是当前焦点,因此无法获取到Back键事件。也就是说只有当Activity是当前焦点时,它才可以捕捉到相应的Back键事件,而有Dialog弹出时,Dialog获取了当前焦点。但是如果我们需要做到相应的需求时,此时有两种思路可以解决这个问题:

Dialog中拦截返回键

  • 一 ) 在Dialog中可以通过调用setOnKeyListener()方法来为Dialog增加按键事件的监听。并重写dispatchKeyEvent方法。
//设置Dialog中的setOnKeyListener
selectDialog.setOnKeyListener(new OnKeyListener() {
    //第一个参数是拦截到此事件的对话框对象的引用,第二个参数是此事件对应的keyCode,第三个参数是此事件对象本身。 
    @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里面就可以实现自己想要实现的操作了。
public boolean dispatchKeyEvent(KeyEvent event)
{
    
    switch(event.getKeyCode())
    {
    case KeyEvent.KEYCODE_BACK:           
        Toast.makeText(getBaseContext(), "点击了back", Toast.LENGTH_SHORT).show();
        break;
    default:
        break;
    }
    return super.dispatchKeyEvent(event);
}
  • 二 ) 在Dialog中可以通过设置Dialog的setOnCancelListener。
//这样就可以捕捉到Back键的事件了,当按下Back键时,系统默认的操作会让Dialog cancel掉,此时会触发OnCancelListener,然后在onCancel方法里面就可以实现自己想要实现的操作了。
selectDialog.setOnCancelListener(new OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
    // TODO Auto-generated method stub
    dialog.dismiss();
    //可以执行你想要实现的操作,我遇到的需求是关闭当前Activity
    finish();
}
});

常用点击事件

  • KeyEvent.KEYCODE_BACK: 表示key类型为返回键
  • KeyEvent.ACTION_DOWN:表示事件为按下key,如果一直按住不放,则会不停产生此事件
  • KeyEvent.ACTION_UP:表示事件为放开key,一次点击key过程只会调用一次

Activity拦截返回键

在Activity的派生类中可以通过重写onKeyDown和onKeyUp这两个方法来拦截返回键。

public boolean onKeyDown(int keyCode, KeyEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);

多个控件的拦截事件的处理

目前在Activity,Dialog和EditText中都可以成功设置拦截事件。如果多个对象设置了拦截事件。则事件只会分发到一个对象上。

通过实验得到如下结论:

1、Dialog优先级最高,如果有一个Activity,Activity中弹出一个Dialog,Dialog中有一个EditText,在Activity,Dialog和EditText中都设置监听,只有Dialog中设置的监听过程能够正确执行。Activity和EditText中的监听过程无法被执行到。

2、Activity优先级次于Dialog,但高于EditText,如果有一个Activity,Activity中有一个EditText,在Activity和EditText中都设置监听,只有Activity中设置的监听过程能够正确执行。EditText中的监听过程无法被执行到。

3、如果当前界面中有PopupWindow,则按返回键后PopupWindow会收到事件通知,并消费(执行dismiss();)。其他设置了监听的对象无法获取到事件通知。(原因是PopupWindow内部布局类PopupViewContainer重写了dispatchKeyEvent()方法)

你可能感兴趣的:(android Dialog在Activity中,如何处理Activity捕捉不到Back点击事件)