如何防止 DialogFragment 在外部触摸时消失?

How to prevent a DialogFragment from dismissing on touch outside?

我正在使用 DialogFragment,它将显示完全自定义的视图,不使用本机按钮。 我使用 dialog.SetCanceledOnTouchOutside(true) 将对话框设置为可取消; 当用户触摸外部时,我想 运行 一些代码来确定是否应该关闭对话框。 我的问题是,当一个事件被触发(取消、解散)时,对话框甚至在 super.Dismiss(); 之前就已经被解散了。所以我永远无法绕过解雇。

我尝试了很多东西,重写片段的 OnDismiss 和 OnCancel(触发但迟到),在对话框本身的 dialogBu​​ilder AND/OR 上设置侦听器(未触发或为时已晚),重写OnShow 重置听众等...

遇到这个问题,有什么想法吗?

PS:使用 Xamarin

public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this.Activity);
    alertDialogBuilder.SetView(myView);
    AlertDialog dialog = alertDialogBuilder.Create();
    dialog.SetCanceledOnTouchOutside(true);
    return dialog;
}

public override void OnDismiss(IDialogInterface dialog)
{
    //BreakPoint here, already dismissed
    base.OnDismiss(dialog);
}

这应该在 onCreateView()

上调用
DialogFragment.getDialog().setCanceledOnTouchOutside(true);

我找到的解决方案是:

just close the fragment only through a cancel button. do your stuff on cancel button click

dialog.Cancelable = false;

_cancelButton =dialog.FindViewById(Resource.Id.btnOptionOne );

_cancelButton.Click += CancelButtonPositiveButtonClick;

private void CancelButtonPositiveButtonClick (object sender, EventArgs e) {
    //do something here and dismiss the dialog if you want to:
    if (satisfied) {
        DismissDialog();
    }
}
private void DismissDialog () {
    _cancelButton.Click -= CancelButtonPositiveButtonClick;
    dialog.Dismiss ();
}

你想达到这个结果吗?如果点击Dialog外部,我们可以检测到Dialog关闭前的点击事件。

您可以创建 MyAlertDialog 继承 AlertDialog

    public class MyAlertDialog:AlertDialog
{
    public MyAlertDialog(Context c):base(c) {

    }

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        //Please add following code for watching outside touch
        this.Window.SetFlags(WindowManagerFlags.NotTouchModal, WindowManagerFlags.NotTouchModal);
        this.Window.AddFlags(WindowManagerFlags.WatchOutsideTouch);
    }



    public override bool OnTouchEvent(MotionEvent e)
    {
        //just used for testing.
        var sss = "test";
        //If you want to close the Dialog when click the outside the Dialog part.
        //this.Dismiss();
        return true;
    }

}

接下来的部分是DialogFragment.

    public class MyDialog:Android.Support.V4.App.DialogFragment
{

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

    }


    public override Dialog OnCreateDialog(Bundle savedInstanceState)
    {


        MyAlertDialog alertDialogBuilder = new MyAlertDialog(this.Activity);
        alertDialogBuilder.SetTitle("MyDialog");
        alertDialogBuilder.SetCanceledOnTouchOutside(true);
        return alertDialogBuilder;
    }



    public override void OnPause()
    {
        base.OnPause();
    }

    public override void OnCancel(IDialogInterface dialog)
    {
        base.OnCancel(dialog);
    }

    public override void OnDismiss(IDialogInterface dialog)
    {
        base.OnDismiss(dialog);
    }
}

点击按钮推送对话框。

private void BtnClick_Click(object sender, System.EventArgs e)
    {
        MyDialog dialog = new MyDialog();
        dialog.Show(SupportFragmentManager, "dialog");
    }

正确的解决方案很简单:

dialog?.setCanceledOnTouchOutside(false)

来自文档:

/**
 * Sets whether this dialog is canceled when touched outside the window's
 * bounds. If setting to true, the dialog is set to be cancelable if not
 * already set.
 * 
 * @param cancel Whether the dialog should be canceled when touched outside
 *            the window.
 */

现在你应该使用 DialogFragment 而不是 AlertDialog 所以答案如下:

isCancelable = false

将其放入代码的任何部分,您就可以为 Java

设置 setCancelable(false)