如何在对话框外部单击以关闭对话框?


Answers:


356

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

就像是,

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

或者,如果您的对话框处于非模型状态,

1- FLAG_NOT_TOUCH_MODAL为对话框的window属性设置flag-

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”,则表示用户正在对话框区域之外进行交互。因此,在这种情况下,您可以取消对话框或决定要执行的操作。查看原图?

public boolean onTouchEvent(MotionEvent event)  
{  

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

有关更多信息,请参见如何关闭基于接触点的自定义对话框?以及 在对话框区域外触摸时如何关闭非模式对话框


9
这很有效,除了下面的活动也对触摸事件做出反应。有什么办法可以防止这种情况?
howettl 2012年

是的 window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL); 导致此问题。我在下面发布了一个解决方案:)
Unknownweirdo 2014年

是否也可以使用非自定义对话框将“触摸外”事件传播到底层活动?
jc 2014年

1
@howettl我已经在我的解决方案中解决了您的问题,该解决方案已在下面发布,我不需要在窗口中设置任何标志。
Roman Nazarevych 2014年

@MuhammedRefaat-请查看此线程groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w。他们很好地描述了它。
user370305 2014年


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


9

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

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

这不适用于我在Samsung Galaxy Tab 2 WiFi上使用的功能。dialog.setCanceledOnTouchOutside(true);确实很棒。
doplumi 2014年

7
dialog.setCanceledOnTouchOutside(true); 

关闭外部触摸对话框。

而且,如果您不想在外面碰触,请使用以下代码:

dialog.setCanceledOnTouchOutside(false);

6

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

如果有,请删除此行:

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);
}

4

您可以尝试以下方法:

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

要么

alertDialog.setCancelable(true);

如果您有,AlterDialog.Builder那么可以尝试以下操作:-

alertDialogBuilder.setCancelable(true);

4

此代码用于在单击时单击hidesoftinput的对话框,以及在用户单击同时关闭softinput和对话框的对话框的外侧时使用的代码。

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;
    }
};

2

另一个解决方案,此代码摘自android源代码,Window 您应该只将这两个方法添加到对话框源代码中。

@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


如果您不希望其他窗口接收事件,您是否只是使对话框变为模态对话框?

1

dialog.setCancelable(false);通过您的活动/片段致电。



0

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


10
答案很差!当然可以做到,但是请以正确的方式来做!
jc 2014年

-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;
        }
    });

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.