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

发布于 2024-12-19 13:47:50 字数 64 浏览 3 评论 0原文

我已经为我的应用程序实现了一个自定义对话框。我想实现当用户在对话框外部单击时,对话框将被关闭。 为此我需要做什么?

I have implemented a custom dialog for my application. I want to implement that when the user clicks outside the dialog, the dialog will be dismissed.
What do I have to do for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

极致的悲 2024-12-26 13:47:51

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

Call dialog.setCancelable(false); from your activity/fragment.

一绘本一梦想 2024-12-26 13:47:51

您可以使背景占据所有屏幕尺寸透明并监听onClick事件以关闭它。

You can make a background occupying all the screen size transparent and listen to the onClick event to dismiss it.

我的影子我的梦 2024-12-26 13:47:51

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

dialog.setOnCancelListener(this);

是改变我的活动来实现 DialogInterface.OnCancelListener

@Override
public void onCancel(DialogInterface dialog) {
     finish();
}

繁荣,它起作用了。

I tried some answers still I faced a problem like when I press outside the dialog dialog was hiding but a dimmed view was showing, and pressing again would go to the parent activity. But actually I wanted to go the parent activity after first click.
So what I did was

dialog.setOnCancelListener(this);

and changed my activity to implement DialogInterface.OnCancelListener with

@Override
public void onCancel(DialogInterface dialog) {
     finish();
}

And boom, it worked.

病毒体 2024-12-26 13:47:51

这是代码

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

试试这个。当你触摸外面时,你可以隐藏键盘

Here is the code

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

Try this one . you can hide the keyboard when you touch outside

暗喜 2024-12-26 13:47:50

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

public boolean onTouchEvent(MotionEvent event)  
{  

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

有关详细信息,请参阅如何取消基于触摸点的自定义对话框?
如何关闭非模式对话框,当触摸到对话框区域之外时

You can use dialog.setCanceledOnTouchOutside(true); which will close the dialog if you touch outside of the dialog.

Something like,

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

Or if your Dialog in non-model then,

1 - Set the flag-FLAG_NOT_TOUCH_MODAL for your dialog's window attribute

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

2 - Add another flag to windows properties,, FLAG_WATCH_OUTSIDE_TOUCH - this one is for dialog to receive touch event outside its visible region.

3 - Override onTouchEvent() of dialog and check for action type. if the action type is
'MotionEvent.ACTION_OUTSIDE' means, user is interacting outside the dialog region. So in this case, you can dimiss your dialog or decide what you wanted to perform.
view plainprint?

public boolean onTouchEvent(MotionEvent event)  
{  

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

For more info look at How to dismiss a custom dialog based on touch points? and
How to dismiss your non-modal dialog, when touched outside dialog region

笑叹一世浮沉 2024-12-26 13:47:50

只需使用

dialog.setCanceledOnTouchOutside(true);

Simply use

dialog.setCanceledOnTouchOutside(true);
⒈起吃苦の倖褔 2024-12-26 13:47:50

您可以使用 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/leading- Activity-by-touching-outside.html

You can use this implementation of onTouchEvent. It prevent from reacting underneath activity to the touch event (as mentioned 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 );
}

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

℉服软 2024-12-26 13:47:50

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

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

Or, if you're customizing the dialog using a theme defined in your style xml, put this line in your theme:

<item name="android:windowCloseOnTouchOutside">true</item>
晚雾 2024-12-26 13:47:50

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

删除此行(如果有):

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

This method should completely avoid activities below the grey area retrieving click events.

Remove this line if you have it:

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

Put this on your activity created

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

then override the touch event with this

@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);
}
无需解释 2024-12-26 13:47:50
dialog.setCanceledOnTouchOutside(true); 

触摸外部时关闭对话框。

如果您不想关闭外部触摸,请使用以下代码:

dialog.setCanceledOnTouchOutside(false);
dialog.setCanceledOnTouchOutside(true); 

to close dialog on touch outside.

And if you don't want to close on touch outside, use the code below:

dialog.setCanceledOnTouchOutside(false);
沙与沫 2024-12-26 13:47:50

你可以尝试这个:-

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

或者

alertDialog.setCancelable(true);

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

alertDialogBuilder.setCancelable(true);

You can try this :-

AlterDialog alterdialog;
alertDialog.setCanceledOnTouchOutside(true);

or

alertDialog.setCancelable(true);

And if you have a AlterDialog.Builder Then you can try this:-

alertDialogBuilder.setCancelable(true);
溺深海 2024-12-26 13:47:50

此代码用于当使用单击对话框时隐藏软输入以及当用户单击对话框的外侧时软输入和对话框都关闭的情况。

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

This code is use for when use click on dialogbox that time hidesoftinput and when user click outer side of dialogbox that time both softinput and dialogbox are close.

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;
    }
};
画离情绘悲伤 2024-12-26 13:47:50

以下对我有用:

myDialog.setCanceledOnTouchOutside(true);

Following has worked for me:

myDialog.setCanceledOnTouchOutside(true);
×纯※雪 2024-12-26 13:47:50

另一种解决方案,此代码取自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

Another solution, this code was taken from android source code of Window
You should just add these Two methods to your dialog source code.

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

This solution doesnt have this problem :

This works great except that the activity underneath also reacts to the touch event. Is there some way to prevent this? – howettl

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文