如何通过单击对话框外部来关闭对话框?

时间:2011-12-05 10:42:09

标签: android android-layout android-emulator dialog android-dialog

我已为我的应用程序实现了自定义对话框。我想实现当用户在对话框外单击时,对话框将被取消。 我该怎么做?

14 个答案:

答案 0 :(得分:334)

如果您在对话框外触摸,可以使用dialog.setCanceledOnTouchOutside(true);关闭对话框。

类似的东西,

  Dialog dialog = new Dialog(context)
  dialog.setCanceledOnTouchOutside(true);

或者如果您的对话在非模型中,那么,

1 - 为对话框的窗口属性设置标志 - FLAG_NOT_TOUCH_MODAL

Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

2 - 向Windows属性添加另一个标志,FLAG_WATCH_OUTSIDE_TOUCH - 此对话框用于在其可见区域之外接收触摸事件。

3 - 覆盖onTouchEvent()对话框并检查操作类型。如果动作类型是 “MotionEvent.ACTION_OUTSIDE”表示用户正在对话区域外进行交互。因此,在这种情况下,您可以减少对话框或决定要执行的操作。 view plainprint?

public boolean onTouchEvent(MotionEvent event)  
{  

       if(event.getAction() == MotionEvent.ACTION_OUTSIDE){  
        System.out.println("TOuch outside the dialog ******************** ");  
               this.dismiss();  
       }  
       return false;  
}  

有关详细信息,请查看How to dismiss a custom dialog based on touch points?How to dismiss your non-modal dialog, when touched outside dialog region

答案 1 :(得分:16)

您可以使用onTouchEvent的此实现。它可以防止在活动下面对触摸事件做出反应(如提到的howettl)。

@Override
public boolean onTouchEvent ( MotionEvent event ) {
  // I only care if the event is an UP action
  if ( event.getAction () == MotionEvent.ACTION_UP ) {
    // create a rect for storing the window rect
    Rect r = new Rect ( 0, 0, 0, 0 );
    // retrieve the windows rect
    this.getWindow ().getDecorView ().getHitRect ( r );
    // check if the event position is inside the window rect
    boolean intersects = r.contains ( (int) event.getX (), (int) event.getY () );
    // if the event is not inside then we can close the activity
    if ( !intersects ) {
      // close the activity
      this.finish ();
      // notify that we consumed this event
      return true;
    }
  }
  // let the system handle the event
  return super.onTouchEvent ( event );
}

来源:http://blog.twimager.com/2010/08/closing-activity-by-touching-outside.html

答案 2 :(得分:14)

只需使用

dialog.setCanceledOnTouchOutside(true);

答案 3 :(得分:9)

或者,如果您使用样式xml中定义的主题自定义对话框,请将此行放在主题中:

<item name="android:windowCloseOnTouchOutside">true</item>

答案 4 :(得分:6)

dialog.setCanceledOnTouchOutside(true); 

在外面触摸时关闭对话框。

如果您不想在外面联系,请使用以下代码:

dialog.setCanceledOnTouchOutside(false);

答案 5 :(得分:5)

此方法应完全避免灰色区域下方检索点击事件的活动。

删除此行,如果您拥有它:

window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);

将此信息放在您创建的活动

getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

然后使用此

覆盖触摸事件
@Override
public boolean onTouchEvent(MotionEvent ev)
{
    if(MotionEvent.ACTION_DOWN == ev.getAction())
    {
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
            // You have clicked the grey area
            displayYourDialog();
            return false; // stop activity closing
        }
    }

    // Touch events inside are fine.
    return super.onTouchEvent(ev);
}

答案 6 :(得分:4)

你可以试试这个: -

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

alertDialog.setCancelable(true);

如果你有AlterDialog.Builder那么你可以试试这个: -

alertDialogBuilder.setCancelable(true);

答案 7 :(得分:2)

此代码的另一个解决方案是从Window的android源代码中删除的 您应该将这两个方法添加到对话框源代码中。

@Override
public boolean onTouchEvent(MotionEvent event) {        
    if (isShowing() && (event.getAction() == MotionEvent.ACTION_DOWN
            && isOutOfBounds(getContext(), event) && getWindow().peekDecorView() != null)) {
        hide();
    }
    return false;
}

private boolean isOutOfBounds(Context context, MotionEvent event) {
    final int x = (int) event.getX();
    final int y = (int) event.getY();
    final int slop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
    final View decorView = getWindow().getDecorView();
    return (x < -slop) || (y < -slop)
            || (x > (decorView.getWidth()+slop))
            || (y > (decorView.getHeight()+slop));
}

此解决方案没有此问题:

  

除了下面的活动也对触摸事件做出反应之外,这种方法很有效。有什么方法可以防止这种情况吗? - howettl

答案 8 :(得分:2)

此代码用于在使用时单击对话框,时间隐藏输入,当用户单击对话框的外侧时,软输入和对话框都关闭。

dialog = new Dialog(act) {
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Tap anywhere to close dialog.
        Rect dialogBounds = new Rect();
        getWindow().getDecorView().getHitRect(dialogBounds);
        if (!dialogBounds.contains((int) event.getX(),
                (int) event.getY())) {
            // You have clicked the grey area
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
            dialog.dismiss();
            // stop activity closing
        } else {
            InputMethodManager inputMethodManager = (InputMethodManager) act
                    .getSystemService(act.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(dialog
                    .getCurrentFocus().getWindowToken(), 0);
        }

        return true;
    }
};

答案 9 :(得分:0)

您可以background占据所有屏幕尺寸transparent并聆听onClick事件至dismiss

答案 10 :(得分:0)

从您的活动/片段中调用dialog.setCancelable(false);

答案 11 :(得分:0)

以下对我有用:

myDialog.setCanceledOnTouchOutside(true);

答案 12 :(得分:0)

我尝试了一些答案,但仍然遇到问题,例如当我在对话框隐藏但显示变暗的视图外按下时,再次按下将转到父活动。但实际上我想在第一次点击后去父活动。 所以我做的是

['2', '4', '9', '4', '9', '9', '6', '7', '7', '7', '8', '7', '8', '8', '9']

并更改了我的 Activity 以实现 dialog.setOnCancelListener(this); with

DialogInterface.OnCancelListener

繁荣,它奏效了。

答案 13 :(得分:-1)

这是代码

    dialog.getWindow().getDecorView().setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent ev) {

            if(MotionEvent.ACTION_DOWN == ev.getAction())
            {
                Rect dialogBounds = new Rect();
                dialog. getWindow().getDecorView().getHitRect(dialogBounds);
                if (!dialogBounds.contains((int) ev.getX(), (int) ev.getY())) {
                    // You have clicked the grey area
                    UiUtils.hideKeyboard2(getActivity());
                    return false; // stop activity closing
                }
            }
            getActivity().dispatchTouchEvent(ev);
            return false;
        }
    });

试试这个。您可以在触摸外部时隐藏键盘