如何在对话框外发生单击时触发事件

时间:2012-03-01 12:29:46

标签: android android-dialog

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

我在活动中弹出一个Dialog。对话框不会覆盖整个屏幕,因此活动中的按钮仍会显示。当对话框与dialog.setCanceledOnTouchOutside(true);

的界限外触摸时,我可以轻松关闭对话框

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

8 个答案:

答案 0 :(得分:51)

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()方法中键入代码,以便在对话框取消时运行。

答案 1 :(得分:36)

对我有用,

        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

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

在扩展DialogFragment的类中使用重写方法onCancel。 。 。

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

答案 6 :(得分:0)

它在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 :(得分:0)

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

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