AndroidX DialogFragment按返回键、点击外部无法关闭问题
问题原因
- 返回键关闭失效:你为Dialog设置的
OnKeyListener在监听到返回键抬起事件时,直接返回true消费了事件,阻断了系统默认的关闭逻辑,但拦截事件后你仅调用了setCanceledOnTouchOutside(true),没有执行任何关闭弹窗的操作,返回键操作自然没有响应。 - 点击外部关闭失效:DialogFragment自身的
isCancelable属性优先级高于内部持有的AlertDialog的对应属性,onStart生命周期会自动把DialogFragment自身的cancel属性同步给内部Dialog,直接覆盖你在onCreateDialog里给AlertDialog设置的cancel配置;加上错误的返回键拦截逻辑干扰了窗口事件分发,最终导致外部触摸的取消判断不生效。
修复方案
- 删掉冗余且逻辑错误的自定义
OnKeyListener,系统默认会处理返回键关闭弹窗的逻辑,不需要额外拦截。如果确实需要自定义返回键逻辑,拦截事件后必须手动调用dismiss()执行关闭。 - 统一在DialogFragment层面设置可取消属性,不要单独给内部的AlertDialog设置cancel相关配置,避免属性被生命周期逻辑覆盖。
修正后的核心实现代码:
private var alertDialog: AlertDialog? = null private var alertDialogBuilder: AlertDialog.Builder? = null private var mainView: View? = null private var rcvBrowserList: RecyclerView? = null private lateinit var browserMenuPopupAdapter: BrowserMenuPopupAdapter val newList = mutableListOf<SubCategory>() override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // 统一设置DialogFragment自身的可取消属性,会自动同步给内部Dialog isCancelable = true alertDialogBuilder = activity?.let { AlertDialog.Builder(it) } mainView = View.inflate(activity, R.layout.layout_broswer_menu, null) alertDialogBuilder?.setView(mainView!!) alertDialog = alertDialogBuilder?.create() alertDialog?.window?.setBackgroundDrawableResource(android.R.color.transparent) alertDialog?.window?.setDimAmount(0.7f) // 移除原有错误的OnKeyListener逻辑 // 若需要自定义返回键逻辑参考如下写法,必须手动调用dismiss // alertDialog?.setOnKeyListener { _, keyCode, event -> // if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { // // 自定义逻辑写在这里 // dismiss() // true // } else false // } findView(mainView!!) return alertDialog as AlertDialog }
补充说明:如果自定义Dialog的布局占满全屏、或者给Window设置了特殊的flags(如
FLAG_NOT_TOUCH_MODAL、FLAG_WATCH_OUTSIDE_TOUCH配置错误),也会导致点击外部无法关闭,这种情况可以检查下Window的属性配置,默认配置下按上述方案修改即可正常生效。
内容的提问来源于stack exchange,提问作者Aashis
相关产品推荐
相关产品推荐

