防止 Android 活动对话框在外部触摸时关闭

281

我有一个使用Theme.Dialog样式的活动,使其成为另一个活动上方的浮动窗口。然而,当我单击对话框窗口之外的区域(即背景活动)时,对话框会关闭。如何停止这种行为?


1
顺便问一下,如果您想要的行为是对话框的行为,为什么不使用对话框呢?至于您的问题,我认为没有解决方案。 - Kumar Bibek
@KumarBibek 当涉及到布局定制时,对话框的限制很大...这就是为什么要使用活动。即使开发者文档也推荐使用此方法进行灵活的自定义。 - Leo
1
而 OP 想要的是一个模态对话框,即强制用户响应的对话框,例如 OK 或 Yes/No。用户不应该能够轻易地点击关闭。 - SMBiggs
20个回答

551

为了防止对话框在按下返回键时被关闭,请使用以下代码:

dialog.setCancelable(false);

为了防止对话框在外部触碰时被关闭,请使用以下方法

 dialog.setCanceledOnTouchOutside(false);

7
这个回答很有帮助,但是这个问题是关于使用 Theme.Dialog 属性的活动。 - Paresh Mayani
19
我知道当我意识到这一点时已经太晚了,因为它对许多人有帮助,所以我没有删除它。 - Singhak
13
我知道这跟问题没有直接关联,但这对我很有帮助。谢谢! - dennisdrew
7
这是最好的答案。我怀疑大部分寻找此问题的人都希望找到一种方法来防止标准“AlertDialog”在触摸外部时关闭,而这个答案提供了这种方法。 - aroth
31
在新版本的AlertDialog中,你只需要使用setCancelable(false)即可。 - Kobi Tate
显示剩余3条评论

132

实际上,您拥有的是一个Activity(即使它看起来像一个Dialog),因此如果您希望在单击背景活动时保持其打开状态,则应从Activity中调用setFinishOnTouchOutside(false)

编辑:仅适用于Android API级别11或更高版本。


5
这并不妨碍您在活动中按“返回”按钮。因此,您还需要重写onBackPressed()方法,并使其为空。 - Alex Bonel
在没有onBackPressed()的对话框Activity中,它无法阻止“返回”按钮。使用this.setFinishOnTouchOutside(false)可以完美解决此问题。 - Kunalxigxag

87

对我有效的方法是创建一个DialogFragment并将其设置为不可取消:

dialog.setCancelable(false);

2
不太有帮助。这个问题是关于活动(Activities),而不是对话框(Dialogs)。 - SMBiggs
所有对话框都属于Dialog类,在AlertDialog的情况下,只需将此标志设置为false,就可以在触摸外部和返回按钮时正常工作。 - Giovanny Piñeros

34

这可能有所帮助。这是一种处理触摸外部事件的方法:

如何在触摸窗口外部时取消类似Activity的对话框主题?

通过捕获事件并不执行任何操作,我认为您可以防止对话框关闭。但令人奇怪的是,您的活动对话框的默认行为应该不是在您触摸外部时关闭自身。

(PS:代码使用WindowManager.LayoutParams)


1
该对象不是对话框,而是使用对话框样式的活动。活动没有这个方法,也无法转换为对话框。 - Fergusmac
你的帖子完全相反于被问到的问题。他问如何防止关闭而不是如何引起关闭。 - ChuckKelly
4
他所解释的是:“通过抓住这个事件并不采取任何行动,我认为你可以阻止关闭。” - metter
4
不知何故,在进行了FLAG_NOT_MODAL和WATCH_OUTSIDE_TOUCH之后,外部触摸实际上并没有关闭活动,而是点击了活动后面的按钮。对此有任何想法吗? - njzk2
请注意,对话框有一个阴影(至少到目前为止(8.0)):如果您单击阴影,Android将解释该单击就像它在对话框内部一样。只是想与世界分享这个,我花了10分钟才明白。 - Lorenzo Von Matterhorn
这不应该是被接受的答案。请参见@Singhak下面的答案。 - Code Wiget

22

在onCreate中将dialog作为一个activity使用时,请添加以下内容

setFinishOnTouchOutside(false);

19

对于API 10及以上版本,当触摸对话框之外的区域时,对话框会消失,而在API 11以下版本中,对话框不会消失。要防止这种情况,您需要执行以下操作:

styles.xml文件中:<item name="android:windowCloseOnTouchOutside">false</item>

或者

onCreate()方法中使用:this.setFinishOnTouchOutside(false);

注意:对于API 10及以下版本,此方法无效,也不需要使用。


18

将对话框的可取消属性设置为false就足够了,无论是在警报对话框外部触摸还是点击后退按钮都会使警报对话框消失。所以使用这个代码:

setCancelable(false)

而另一个函数已经不再必要: dialog.setCanceledOnTouchOutside(false);

如果你正在创建一个临时对话框并想知道把这行代码放哪里,这里是一个例子:

new AlertDialog.Builder(this)
                        .setTitle("Trial Version")
                        .setCancelable(false)
                        .setMessage("You are using trial version!")
                        .setIcon(R.drawable.time_left)
                        .setPositiveButton(android.R.string.yes, null).show();

16

警告对话框已过时,请使用Dialog dialog = new Dialog(this)。

要防止在外部触摸时关闭,请使用以下代码:

dialog.setCanceledOnTouchOutside(false);

15

使用这段代码,对我来说有效

 AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
 alertDialog.setCancelable(false);


如果他能提出正确的问题,那么这将是正确的答案! - alijunior
2
如果提问者询问的是对话框,那么这将是正确的答案!但问题是关于Activities——完全不同的情况。 - SMBiggs
所以,.setCanceledOnTouchOutside(false) 只能在 .create() 之后访问。 - francis

14
Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true); 
//use this to dismiss the dialog on outside click of dialog

dialog.setCanceledOnTouchOutside(false);
//use this for not to dismiss the dialog on outside click of dialog.

点击这个链接获取更多关于对话框的详细信息。

dialog.setCancelable(false);
//used to prevent the dismiss of dialog on backpress of that activity

dialog.setCancelable(true);
//used to dismiss the dialog on onbackpressed of that activity

请注意,该问题涉及用作对话框的 Activities,而不是 Dialog 类。 - SMBiggs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接