本节摘要:输入事件按粒度分三层——单击与长按是成品手势,触摸是原始轨迹,键盘是文本通道。本节给猜数字 App 接齐三类输入:长按标题显示答案彩蛋、触摸滑动清空输入、软键盘"完成"直接提交,并处理返回键拦截这一高频需求。
单击上一节讲透了,长按只是多一个监听器,但它的交互语义值得单独说:长按适合低频、有破坏性或"藏起来"的操作。猜数字 App 把答案范围做成彩蛋——长按标题两秒,弹出真实提示:
binding.tvTitle.setOnLongClickListener { Toast.makeText(this, "答案是 1 到 100 里的某个数", Toast.LENGTH_SHORT).show() true // 消费长按,避免再触发单击 }
返回值沿用上一节的消费语义:返回 true 告诉系统长按已被处理,同一按次不会再派发单击。返回 false 的后果是长按松手后又补一次 onClick,用户会看到彩蛋和提交动作接连触发——两个监听器打架时,先查返回值。
View 还提供了便捷的 isClickable、performClick():前者控制控件可否响应点击(默认 Button 可点、TextView 不可点),后者在代码里模拟一次点击。上一节 onTouch 例子里调 performClick 正是为了保住无障碍语义——读屏辅助服务依赖 click 事件播报"已点击",绕过它自己发动画是常见的无障碍事故。
onTouch 拿到的是未加工的 MotionEvent 流:ACTION_DOWN 一枚、ACTION_MOVE 若干、ACTION_UP 收尾,event.x / event.y 给出指尖相对控件左上角的坐标。做一个"甩掉输入"的交互——在输入框上快速左滑即清空:
binding.etGuess.setOnTouchListener { v, event -> when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { startX = event.x false // 不消费,点击照常 } MotionEvent.ACTION_UP -> { val dx = event.x - startX if (dx < -120) { // 左滑超过 120px 视为甩动 binding.etGuess.text.clear() Toast.makeText(this, "已清空", Toast.LENGTH_SHORT).show() v.performClick() true } else false } else -> false } }
两处设计说明:DOWN 返回 false 让单击与焦点行为不受影响,只有确认是甩动后才消费——消费点尽量晚,正常手势尽量不惊扰;阈值用像素只是演示,正式代码应换算成 dp 以适配不同密度屏幕(2.2 节的换算工具在这等着)。
软键盘不只会输入字符,右下角那颗动作键是可以接管的。1.1 节已经给 EditText 配了 imeOptions="actionDone",这里补全代码与另一种常用形态——"下一项":
binding.etGuess.setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { binding.btnGuess.performClick() // 复用提交逻辑,不复制粘贴 true } else false }
注意 performClick() 的用法:提交逻辑只写在按钮的 onClick 里,键盘路径通过模拟点击汇入同一段代码——一个动作一条逻辑,两个入口,复制粘贴两份逻辑必然在日后改动时漏改一半。
返回键是另一条必经之路。猜数字进行到一半按返回键,直接退出太粗暴,拦下来问一句"确定放弃本局吗":
override fun onBackPressed() { if (game.inProgress) { showGiveUpDialog() // 确认后 finish() } else { super.onBackPressed() } }

多点触控要不要现在学? 单指场景用 actionMasked 加索引已经够用;双指缩放这类需求优先找现成手势工具类(如系统的 ScaleGestureDetector),别自己解析原始多点事件——那是另一个深度的坑,等真实需求来了再跳不迟。
所有控件都该能点吗? 恰恰相反,可点区域要克制。界面上每个可点元素都在向用户承诺"点了有事发生",承诺过多而兑现不了,信任就贬了值。不可点的装饰元素保持默认不可点状态,读屏与点击意图都干净,这既是交互设计也是无障碍礼貌。
最后提醒一个测试习惯:任何新接的输入路径都要做"暴力测试"——快速连点、长按后滑动、输入框里粘贴超长文本、转屏瞬间按键。输入事件的 bug 几乎都藏在非常规操作序列里,发布前五分钟的暴力测试,抵得上用户群里一晚上的吐槽。
键盘处理还有一个易漏角落:返回焦点管理。多个输入框顺序填写时,imeOptions 配 actionNext 可以在键盘上一路"下一项"走到提交,这比每格都点一下省一半操作;而输入完成后主动收起键盘,是许多 App 缺失的最后一厘米礼仪。