【问题标题】:How to dismiss the dialog with click on outside of the dialog?如何通过单击对话框外部来关闭对话框?
【发布时间】:2012-01-13 02:52:30
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

    类似的,

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

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

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

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

    【讨论】:

    • 这很好用,只是下面的活动也会对触摸事件做出反应。有什么方法可以防止这种情况发生吗?
    • 是的。 window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);导致这个问题。我在下面发布了一个解决方案:)
    • 是否也可以使用非自定义对话框将“on-touch-outside”事件传播到下面的活动?
    • @howettl 我已经在我的解决方案中解决了您的问题我在下面发布了,我不需要为窗口设置任何标志。
    • @MuhammedRefaat - 请查看此线程groups.google.com/forum/#!topic/android-developers/VhaiIMl6E_w。他们很好地描述了它。
    【解决方案2】:

    简单地使用

    dialog.setCanceledOnTouchOutside(true);
    

    【讨论】:

    • 我知道这应该是正确的答案,但对我不起作用,我只是不知道为什么。
    【解决方案3】:

    您可以使用 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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 这对我在三星 Galaxy Tab 2 WiFi 上不起作用。 dialog.setCanceledOnTouchOutside(true); 确实工作得很好。
      【解决方案5】:
      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);
        }
        

        【讨论】:

          【解决方案7】:

          你可以试试这个:-

          AlterDialog alterdialog;
          alertDialog.setCanceledOnTouchOutside(true);
          

          alertDialog.setCancelable(true);
          

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

          alertDialogBuilder.setCancelable(true);
          

          【讨论】:

            【解决方案8】:

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

            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】:

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

              这个解决方案没有这个问题:

              这很好用,只是下面的活动也会对触摸事件做出反应。有什么方法可以防止这种情况吗? – 豪特尔

              【讨论】:

              • 如果您不希望其他窗口接收事件,您就不能让您的对话框触摸模态吗?
              【解决方案10】:

              以下对我有用:

              myDialog.setCanceledOnTouchOutside(true);
              

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  【解决方案12】:

                  您可以制作一个background 占据所有屏幕尺寸transparent 并将onClick 事件监听到dismiss 它。

                  【讨论】:

                  • 非常糟糕的答案!这当然可以,但请以正确的方式进行!
                  【解决方案13】:

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

                  dialog.setOnCancelListener(this);
                  

                  并更改了我的活动以实现DialogInterface.OnCancelListener

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

                  然后繁荣,它奏效了。

                  【讨论】:

                    【解决方案14】:

                    这里是代码

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

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

                    【讨论】:

                      猜你喜欢
                      • 2023-02-16
                      • 1970-01-01
                      • 2021-11-24
                      • 1970-01-01
                      • 2012-01-08
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多