【问题标题】:How do I fire an event when click occurs outside a dialog在对话框外发生单击时如何触发事件
【发布时间】:2012-03-19 22:51:12
【问题描述】:

我想知道如何解决我遇到的问题。

我有一个在活动中弹出的对话框。对话框没有覆盖整个屏幕,因此活动中的按钮仍然显示。当在对话框边界之外触摸dialog.setCanceledOnTouchOutside(true);时,我可以轻松关闭对话框

但是,如果单击超出 Dialog 的范围,我想做的是触发事件(例如,如果有人触摸主 Activity 上的按钮,它应该关闭 Dialog 并同时触发该事件)。

【问题讨论】:

  • 正常的解决方案是使对话框模式化。你为什么不想这样做?
  • 谢谢。我试图在我的主要活动中显示一个 webview(在对话框中),以便它保持应用程序的外观。

标签: android android-dialog


【解决方案1】:

dialog.setCanceledOnTouchOutside(true); 时,您只需像这样覆盖onCancel()

dialog.setOnCancelListener(
        new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                //When you touch outside of dialog bounds, 
                //the dialog gets canceled and this method executes.
            }
        }
);

onCancel() 方法中输入您的代码,以便在对话框取消时运行。

【讨论】:

  • 最佳答案.. 2 年后也参考相同的答案...无法再次投票:)
  • OVERRIDING Dialog.onCancel(...) 有效,但 dialog.setOnCancelListener(...) 对我不起作用。
  • 什么时候? - When dialog.setCanceledOnTouchOutside(true); 这是默认行为...
  • 这应该是公认的答案!!多么棒的答案。
【解决方案2】:

它对我有用,

        Window window = dialog.getWindow();
        window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

        dialog.show();

看到这个http://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_NOT_TOUCH_MODAL

【讨论】:

  • 这有点用。只有我可以滚动列表视图但不能单击它。
【解决方案3】:

DialogFragment 中你可以使用AlertDialog@silverTech 的答案:

override fun onDismiss(dialog: DialogInterface) {
    yourMethod()
    super.onDismiss(dialog)
}

override fun onCancel(dialog: DialogInterface) {
    yourMethod()
    super.onCancel(dialog)
}

【讨论】:

  • 为什么建议在 super.onDismiss() 之前插入逻辑?那为什么super.onCancel()后面是逻辑呢?
  • @AJW,我打开了DialogFragmentonCancel 是空的,而 onDismiss 包含一些关于关闭(关闭)对话框的逻辑。我建议先编写您的逻辑,然后再销毁方法(super.onPause()onDestroyonSaveInstanceState 等)。最好在系统销毁对象之前完成变量。所以,也许最好删除super.onCancel(dialog)。在您发表评论后,我重写了onCancel,谢谢。
【解决方案4】:

您可以使用OnCancelListener 在对话框外发生点击时触发事件:

dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        yourFunction();
    }
});

【讨论】:

【解决方案5】:

如果您在自定义对话框类中,并且希望捕捉“点击外部”事件 - 覆盖取消()。如果你想捕捉“对话框关闭”事件 - 覆盖dismiss()。 我建议在 super.dismiss() 之前插入逻辑。 Kotlin 示例:

override fun dismiss() {
    Utils.hideKeyboard(mContext, window)
    super.dismiss()
}

【讨论】:

  • 不是一个很好的答案。意思是,它不是通用的。我必须写新的行为,而不是注意到旧的行为。在我制作通用对话框实用程序的情况下,我无法知道对话框背后的内容。
  • @JaveneCPPMcGowan 您可以使用自定义对话框中的回调到视图。
  • 正如我所说,这是新的行为。
  • @SilverTech 为什么建议在 super.dismiss() 之前插入逻辑?
  • 反之则造成了只有有时 hideKeyboard 函数才能按预期工作的情况。
【解决方案6】:

它可以在com.google.android.material.bottomsheet.BottomSheetDialog获得

> // We treat the CoordinatorLayout as outside the dialog though it is technically inside
>     coordinator
>         .findViewById(R.id.touch_outside)
>         .setOnClickListener(
>             new View.OnClickListener() {
>               @Override
>               public void onClick(View view) {
>                 if (cancelable && isShowing() && shouldWindowCloseOnTouchOutside()) {
>                   cancel();
>                 }
>               }
>             });

这样您就可以在 BottomSheetDialog 覆盖 ClickListener

class MyBottomDialogFragment : BottomSheetDialogFragment(){
 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = object : BottomSheetDialog(activity as Context, theme) {
            private var isDialogCancelable: Boolean = false
            private var isDialogCancelableOnTouchOutside: Boolean = false

            override fun onBackPressed() {
                handleBackPressed(this)
            }

            override fun setContentView(layoutResId: Int) {
                super.setContentView(layoutResId)
                setupTouchOutside()
            }

            override fun setContentView(view: View?) {
                super.setContentView(view)
                setupTouchOutside()
            }

            override fun setContentView(view: View?, params: ViewGroup.LayoutParams?) {
                super.setContentView(view, params)
                setupTouchOutside()
            }

            private fun setupTouchOutside() {
                val coordinator = findViewById<View>(com.google.android.material.R.id.coordinator) as CoordinatorLayout
                // We treat the CoordinatorLayout as outside the dialog though it is technically inside
                coordinator
                    .findViewById<View>(com.google.android.material.R.id.touch_outside)
                    .setOnClickListener {
                        if (isDialogCancelable && isShowing && isDialogCancelableOnTouchOutside) {
                            handleTouchOutside(this)
                        }
                    }
            }


            override fun setCancelable(cancelable: Boolean) {
                super.setCancelable(cancelable)
                isDialogCancelable = cancelable
            }

            override fun setCanceledOnTouchOutside(cancel: Boolean) {
                super.setCanceledOnTouchOutside(cancel)
                isDialogCancelableOnTouchOutside = cancel
            }
        }
        dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        dialog.setCanceledOnTouchOutside(true)
        return dialog
    }

  protected open fun handleBackPressed(dialog: BottomSheetDialog) {
        /* do what you want but after that call dialog.cancel() or dialog.dismiss() */
    }

    protected open fun handleTouchOutside(dialog: BottomSheetDialog) {
        /* do what you want but after that call dialog.cancel() or dialog.dismiss() */        
    }
}

【讨论】:

    【解决方案7】:

    使用返回按钮命令返回上一屏幕。

    在扩展 DialogFragment 的类中使用覆盖方法 onCancel。 . .

    @Override
        public void onCancel(@NonNull DialogInterface dialog)
        {
            super.onCancel(dialog);
            getParentFragment().getActivity().onBackPressed();
        }
    

    【讨论】:

      【解决方案8】:

      我发现所有其他答案都非常冗长和复杂,所以我使用了这种方法:

      第 1 步: 为要为其生成点击外部事件的元素的外部容器创建一个 ID。

      在我的例子中,它是一个线性布局,我将其 id 指定为“outsideContainer”

      第 2 步: 为该外部容器设置一个 onTouchListener,它只会充当您内部元素的外部点击事件!

      outsideContainer.setOnTouchListener(new View.OnTouchListener() {
                                                  @Override
                                                  public boolean onTouch(View v, MotionEvent event) {
                                                      // perform your intended action for click outside here
                                                      Toast.makeText(YourActivity.this, "Clicked outside!", Toast.LENGTH_SHORT).show();
                                                      return false;
                                                  }
                                              }
          );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-28
        • 1970-01-01
        相关资源
        最近更新 更多