Kotlin开发中Pixel与三星安卓设备隐藏键盘的行为差异及修复咨询
三星设备软键盘适配异常修复方案
问题根因
现有dispatchTouchEvent逻辑未做触摸区域判断,只要页面存在焦点控件就会无条件收起软键盘。三星ROM对触摸事件分发时序做了定制:点击发送按钮时,dispatchTouchEvent先接收到ACTION_DOWN事件,此时立即执行的软键盘收起逻辑会触发输入框失焦、页面布局重排,导致后续的ACTION_UP事件无法命中发送按钮,点击回调因此不会触发。原生Pixel设备的事件分发优先级不同,点击事件判断先于软键盘收起的副作用,因此运行正常。
修复思路
仅在用户点击输入框和发送按钮之外的区域时,才触发软键盘收起操作,避免打断发送按钮的点击事件链路。
修复后代码
override fun dispatchTouchEvent(ev: MotionEvent): Boolean { // 仅处理按下事件,避免重复执行逻辑 if (ev.action == MotionEvent.ACTION_DOWN) { val focusView = currentFocus // 仅当前焦点为输入框时做区域判断 if (focusView is EditText) { // 获取输入框在屏幕中的坐标范围 val editPos = IntArray(2) focusView.getLocationOnScreen(editPos) val editRect = Rect( editPos[0], editPos[1], editPos[0] + focusView.width, editPos[1] + focusView.height ) // 获取发送按钮在屏幕中的坐标范围,sendBtn替换为你的实际发送按钮实例 val sendBtnPos = IntArray(2) sendBtn.getLocationOnScreen(sendBtnPos) val sendBtnRect = Rect( sendBtnPos[0], sendBtnPos[1], sendBtnPos[0] + sendBtn.width, sendBtnPos[1] + sendBtn.height ) val touchX = ev.rawX.toInt() val touchY = ev.rawY.toInt() // 触摸点既不在输入框区域也不在发送按钮区域时,才收起软键盘 if (!editRect.contains(touchX, touchY) && !sendBtnRect.contains(touchX, touchY)) { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(focusView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS) focusView.clearFocus() } } } return super.dispatchTouchEvent(ev) }
补充优化建议
- 如果页面存在多个需要保留点击响应的控件,可以把这些控件的区域判断都加到条件中,只要触摸点落在这些控件范围内就跳过收键盘逻辑
- 对比硬编码传0,使用
InputMethodManager.HIDE_NOT_ALWAYS作为收起参数的兼容性更好,不会强制打断正在进行的交互操作

内容的提问来源于stack exchange,提问作者Mohamed Eweidat
相关产品推荐
相关产品推荐

