Android 在对话框外单击时如何触发事件
我想知道如何解决我遇到的问题 我有一个在活动中弹出的对话框。对话框没有覆盖整个屏幕,因此活动中的按钮仍然显示。当使用Android 在对话框外单击时如何触发事件,android,android-dialog,Android,Android Dialog,我想知道如何解决我遇到的问题 我有一个在活动中弹出的对话框。对话框没有覆盖整个屏幕,因此活动中的按钮仍然显示。当使用dialog.setCanceledOnTouchOut(true)在对话框边界之外有一个触摸时,我可以轻松地关闭对话框 但是,我想做的是,如果单击超出对话框的范围,则触发一个事件(例如,如果有人触摸主活动上的按钮,则应关闭对话框并同时触发该事件)。它对我有效 Window window = dialog.getWindow(); window.se
dialog.setCanceledOnTouchOut(true)在对话框边界之外有一个触摸时,我可以轻松地关闭对话框代码>
但是,我想做的是,如果单击超出对话框的范围,则触发一个事件(例如,如果有人触摸主活动上的按钮,则应关闭对话框并同时触发该事件)。它对我有效
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();
当对话框时,查看此。将取消设置为外部(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()
方法中键入代码,以便在取消对话框时运行。当在对话框外单击时,可以使用触发事件:
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
yourFunction();
}
});
如果您在自定义对话框类中,并且希望捕获“单击外部”事件-覆盖取消()。如果希望捕获“对话框已关闭”事件,请覆盖Disclose()。
我建议在super.disclose()之前插入逻辑。科特林示例:
override fun dismiss() {
Utils.hideKeyboard(mContext, window)
super.dismiss()
}
在DialogFragment
中,您可以使用AlertDialog
和以下答案:
或
使用“后退”按钮命令返回上一屏幕
在扩展DialogFragment的类中使用重写方法onCancel
@Override
public void onCancel(@NonNull DialogInterface dialog)
{
super.onCancel(dialog);
getParentFragment().getActivity().onBackPressed();
}
其网址为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();
> }
> }
> });
因此,您可以在您的对话框中覆盖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() */
}
}
类MyBottomDialogFragment:BottomSheetDialogFragment(){
重写FunonCreateDialog(savedInstanceState:Bundle?:对话框){
val dialog=object:BottomSheetDialog(活动作为上下文、主题){
私有变量isDialogCancelable:Boolean=false
私有变量isDialogCancelableOnTouchOutside:Boolean=false
重写函数onBackPressed(){
把手压住了(这个)
}
覆盖有趣的setContentView(layoutResId:Int){
super.setContentView(layoutResId)
setupTouchOutside()
}
覆盖内容视图(视图:视图?){
super.setContentView(视图)
setupTouchOutside()
}
覆盖有趣的setContentView(视图:view?,参数:ViewGroup.LayoutParams?){
super.setContentView(视图,参数)
setupTouchOutside()
}
私人娱乐场所(户外){
val coordinator=findViewById(com.google.android.material.R.id.coordinator)作为协调人布局
//我们将CoordinatorLayout视为对话框外部,尽管它在技术上是内部的
协调员
.findviewbyd(com.google.android.material.R.id.touch\u外部)
.setOnClickListener{
如果(isDialogCancelable&&isShowing&&IsDialogCancelableOnTouchOut){
手槽外侧(此)
}
}
}
覆盖乐趣可设置可取消(可取消:布尔值){
super.setCancelable(可取消)
isDialogCancelable=可取消
}
覆盖fun setCanceledOnTouchOutside(取消:布尔值){
super.setCanceledOnTouchOut(取消)
isDialogCancelableOnTouchOutside=取消
}
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT\u INPUT\u ADJUST\u RESIZE)
对话框。setCanceledOnTouchOutside(真)
返回对话框
}
受保护的开放式趣味把手已按下(对话框:底部挡板对话框){
/*在调用dialog.cancel()或dialog.discouse()之后,执行您想要的操作*/
}
受保护的开放式趣味手柄(对话框:底部挡板对话框){
/*在调用dialog.cancel()或dialog.discouse()之后,执行您想要的操作*/
}
}
我发现所有其他答案都相当冗长和复杂,因此我采用了这种方法:
第1步:
为要为其生成单击外部事件的元素的外部容器创建ID
在我的例子中,它是一个线性布局,我将其id指定为“outsideContainer”
第二步:
为外部容器设置一个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;
}
}
);
通常的解决方案是使对话框成为模态。你为什么不想那样做?谢谢。我试图在我的主要活动中显示一个webview(在对话框中),以便它保持应用程序的外观。最佳答案。。两年后,我也引用了同样的答案…无法再次投票:)覆盖Dialog.onCancel(…)有效,但Dialog.setOnCancelListener(…)对我无效。你说什么时候?-<代码>当dialog.setCanceledOnTouchOutside(真)时代码>这是默认行为…这应该是公认的答案!!多好的回答啊,这很有效。只是我可以滚动列表视图,但不能点击它。这不是一个很好的答案。也就是说,它不是泛型的。我必须写新的行为,而不是注意旧的行为。在我制作通用对话框实用程序的情况下,我无法知道对话框背后是什么。@JaveneCPPMcGowan您可以使用从自定义对话框到视图的回调。正如我所说的,这是一种新的行为。@SilverTech为什么建议在super.disclose()之前插入逻辑?另一种情况是,hideKeyboard函数有时只能按预期工作。它与@WillNeithan answer()有什么区别?为什么建议在super.onDismiss()之前插入逻辑?那么为什么super.onCancel()之后是逻辑呢?@AJW,我打开了对话框片段
onCancel
为空,而onDismiss
包含一些关于dismissing(clo)的逻辑
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() */
}
}
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;
}
}
);