Android按返回键单次同时隐藏键盘并关闭BottomSheetFragment问题
问题根源
- 安卓系统的按键事件分发优先级为:当前持有焦点的控件(这里是激活了软键盘的输入框)> 弹窗的全局按键监听
- 首次点击返回键时,事件优先被软键盘消费触发隐藏,不会传递到你为Dialog设置的OnKeyListener,所以只有键盘关闭,弹窗没有响应
- 第二次点击返回键时软键盘已经隐藏,事件才会传递到Dialog的监听逻辑,触发弹窗关闭
修复方案
这里提供两种经过验证的实现方式,任选一种即可:
方案1:修改Dialog按键拦截逻辑(适配性更强)
替换你原来onCreateDialog和onResume中的按键监听代码,统一在Dialog层拦截返回事件,同时处理软键盘隐藏和弹窗关闭:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) dialog.setOnKeyListener { _, keyCode, event -> // 只处理返回键的抬起事件,避免重复触发 if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { // 隐藏软键盘 val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(et_add_comment.windowToken, 0) // 关闭弹窗 dismiss() return@setOnKeyListener true } false } return dialog }
修改完成后记得删除onResume方法中旧的setOnKeyListener代码,避免逻辑冲突。
方案2:给输入框设置按键监听(实现更简单)
如果你的弹窗全程只有输入框持有焦点,可以直接给输入框设置按键监听,软键盘触发的返回事件会优先传递给持有焦点的输入框:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) et_add_comment.setOnKeyListener { _, keyCode, event -> if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { // 直接关闭弹窗,系统会自动同步隐藏绑定到输入框的软键盘 dismiss() return@setOnKeyListener true } false } }
注意:需要导入
android.view.KeyEvent、android.view.inputmethod.InputMethodManager相关类即可正常编译,你原有的Dialog style配置不需要做任何修改。
内容的提问来源于stack exchange,提问作者Ahmad Nasser
相关产品推荐
相关产品推荐

