检测后退按钮,但不要忽略对话碎片

时间:2014-01-23 12:14:34

标签: android dialog dialogfragment

我有一个浮动对话框的对话框片段,其中包含一个特殊的键盘,当用户在EditText字段内按下时会弹出(正常的IME停止显示)。

当用户按下后退按钮(就像使用普通的IME服务一样)时,我希望键盘被解除(visibility = GONE),但对话框仍然可见。但是,就我在SO和其他地方的相当广泛的阅读中所看到的,似乎没有办法做到这一点。

如果我将对话框设置为不可取消,那么我不会被onCancel()或onDismiss()通知,因为该对话框不可取消。

如果我将对话框设置为可取消,则会收到通知,但对话框将被取消。

我无法将onKeyListener附加到片段中的对话框,因为它被系统替换,以便片段可以处理对话框的生命周期。

有没有办法做到这一点?或者,为了Fragment系统的目的,是否可以访问完全围起来的关键事件的检测?

10 个答案:

答案 0 :(得分:131)

最好的方法和最干净的方法是在onCreateDialog()中创建的对话框中覆盖onBackPressed()。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), getTheme()){
        @Override
        public void onBackPressed() {
            //do your stuff
        }
    };
}

答案 1 :(得分:62)

我遇到了与你相同的问题,并且我已经修复了将onKeyListener附加到对话片段的问题。

在DialogFragment扩展类的方法onResume()中放置这些代码:

    getDialog().setOnKeyListener(new OnKeyListener()
    {
        @Override
        public boolean onKey(android.content.DialogInterface dialog, int keyCode,android.view.KeyEvent event) {

            if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
                {
                     //Hide your keyboard here!!!
                     return true; // pretend we've processed it
                }
            else 
                return false; // pass on to be processed as normal
        }
    });

这里可以找到的问题之一是这个代码将被执行两次:一个是用户按下后退按钮而另一个是当他离开按下它时。在这种情况下,您必须按事件过滤:

@Override
public void onResume() {
    super.onResume();

    getDialog().setOnKeyListener(new OnKeyListener()
    {
        @Override
        public boolean onKey(android.content.DialogInterface dialog, int keyCode,
                android.view.KeyEvent event) {

            if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
            {
                //This is the filter
                if (event.getAction()!=KeyEvent.ACTION_DOWN)
                        return true;
                else
                {
                    //Hide your keyboard here!!!!!!
                    return true; // pretend we've processed it
                }
            } 
            else 
                return false; // pass on to be processed as normal
        }
    });
}

答案 2 :(得分:17)

作为胡安·佩德罗·马丁内斯答案的附录,我认为在查看这个帖子时澄清一个具体问题(我有一个问题)会有所帮助。

如果你想创建一个新的DialogFragment,并且让用户只能使用后退按钮取消它,这会消除随机屏幕触摸过早取消片段,那么这就是你要使用的代码。

在您调用DialogFragment的代码中,您需要将可取消设置设置为false,以便NOTHING解散片段,不会出现杂散屏幕触摸等。

DialogFragment mDialog= new MyDialogFragment();
mDialog.setCancelable(false);
mDialog.show(getFragmentManager(), "dialog");

然后,在DialogFragment中,在本例中为MyDaialogFragment.java,添加onResume覆盖代码以使对话框侦听后退按钮。当它被按下时,它将执行dismiss()来关闭片段。

@Override
 public void onResume() 
 {
     super.onResume();

     getDialog().setOnKeyListener(new OnKeyListener()
     {
         @Override
         public boolean onKey(android.content.DialogInterface dialog, 
                              int keyCode,android.view.KeyEvent event) 
         {
              if ((keyCode ==  android.view.KeyEvent.KEYCODE_BACK))
              {
                   // To dismiss the fragment when the back-button is pressed.
                   dismiss();
                   return true;
              }
              // Otherwise, do nothing else
              else return false;
         }
   });

现在,您的对话框将使用" setCancelable"为假,没有任何意义(没有外部点击)可以取消它并关闭它,并允许(从对话框本身)只有后退按钮关闭它。

Ganbatte!

答案 3 :(得分:6)

没人提出这个建议?

public Dialog onCreateDialog(Bundle savedInstanceState) {
  Dialog dialog = super.onCreateDialog(savedInstanceState);

  // Add back button listener
  dialog.setOnKeyListener(new Dialog.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialogInterface, int keyCode, KeyEvent keyEvent) {
      // getAction to make sure this doesn't double fire
      if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_UP) {
        // Your code here
        return true; // Capture onKey
      }
      return false; // Don't capture
    }
  });

  return dialog;
}

答案 4 :(得分:3)

使用Fragment onCancel覆盖方法。按下时会调用它。 这是一个示例:

@Override
public void onCancel(DialogInterface dialog) {
    super.onCancel(dialog);

    // Add you codition
}

答案 5 :(得分:1)

if (strEndsWith(person.lastName, "ian")) {
    fprintf(arm, "%s, %s\n", person.lastName, person.firstName);
}

答案 6 :(得分:0)

创建对话框时,覆盖onBackPressed和onTouchEvent:

Settings

答案 7 :(得分:0)

使用带有 closeActivity 标志

的DialogFragment的onDismiss()回调

private var closeActivity: Boolean = true    

override fun onDismiss(dialog: DialogInterface?) {
        super.onDismiss(dialog)

        if (closeActivity) {
            activity!!.finish()
        }
    }

答案 8 :(得分:0)

防止取消DialogFragment:

dialog.setCanceledOnTouchOutside(false)
dialog.setCancelable(false)
dialog.setOnKeyListener { dialog, keyCode, event ->
    keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP
}

答案 9 :(得分:-1)

AndroidX OnBackPressedDispatcher也可以作为某人的选择