同一份内测包,你在自己手机上点输入框,键盘弹上来,页面顺顺当当顶起;测试用户发来的截图里,按钮却被键盘盖住了半截。这类问题反馈里很多,但开发者自己的设备往往复现不了,机型、系统版本、输入法、字号设置任何一项不同,结果都可能不一样。下面按「先定位、再分端修、最后验收」的顺序整理一遍。
先分清是遮挡还是没顶到位
描述「键盘挡住」时其实混了三种情况,处理方向完全不同。
- 页面完全没动,输入框留在键盘下方:布局没有响应键盘高度。
- 页面动了,但只露出半行:位移量算错,常见于写死高度或按屏幕比例计算。
- 收起键盘后底部留一片空白,回不到原位:状态没有复原,多半是监听只做了一半。
判断办法很简单:录屏,并在安卓开发者选项里打开「显示布局边界」,看输入框与键盘的位置关系。有了录屏,开发和测试对的是同一个现象,不用来回描述。
安卓侧:先看清单配置,再看沉浸式
- 打开
AndroidManifest.xml,确认对应 Activity 的android:windowSoftInputMode取值为adjustResize。设为adjustPan时页面整体上推,悬浮按钮容易跑出可视区。 - 若
adjustResize不生效,先检查页面是否开了全屏或沉浸式。setDecorFitsSystemWindows(false)之后系统不再自动重算可视区域,需要自己接管 inset。 - 用
WindowInsets监听键盘高度,把这段高度交给滚动容器,不要给根布局加固定margin,否则键盘收起后会留下空隙。 - 底部固定按钮要在键盘弹出时单独上移。只滚内容区不动按钮,是新手最常踩的坑。
iOS 侧:别写死键盘高度
- 监听
keyboardWillShow与keyboardWillHide,用通知里带回的结束高度和动画时长,不要硬编码 216 或 291 这类历史数值。 - 计算时减去
safeAreaInsets.bottom,否则全面屏机型会多顶一段,出现明显跳动。 UIScrollView场景改contentInset.bottom比改frame更稳,键盘收起时记得归零。- 动画时长与曲线跟键盘保持一致,否则会看到一帧错位。
中文输入法那一环最容易漏
用拼音打字的用户,在候选词阶段会连续触发输入事件,这部分逻辑与英文输入差别很大。
- 组合中的文本不要立即触发搜索、校验或字数结算,等上屏后再处理。
- 安卓侧
setComposingText与commitText要分开处理,混在一起会导致重复提交或漏字。 - 部分输入法把回车键用作上屏,不要同时绑定成「提交表单」,否则用户选词时就被提交了。
- 字数限制按真实字符计算,emoji 与组合字符用
codePointCount而不是length。
验收:把机型与输入法拉齐
| 检查项 | 具体做法 |
|---|---|
| 系统版本 | 至少覆盖安卓一个旧版本、一个最新版本 |
| 输入法 | 系统自带加一款第三方拼音输入法各测一遍 |
| 字号与显示 | 系统字号调到最大,看文案是否被裁切 |
| 屏幕形态 | 小屏与大屏机型各一台,重点看底部按钮 |
把这张表写进提测单,比每次口头提醒「记得测键盘」有效。提测包上传到 虾分发 后,可以在应用说明里附一句「反馈请注明机型与输入法」,收集到的信息会完整很多。
常见问题
| 问题 | 可能原因 | 处理方向 |
|---|---|---|
| 键盘弹出一半就停住 | 高度取自旧回调或缓存值 | 用最新一次通知里的高度重新计算 |
| 输入框在弹窗里被遮挡 | 弹窗未跟随键盘位移 | 弹窗单独监听键盘事件 |
| 只有某款第三方输入法出问题 | 输入法自绘候选栏,高度不同 | 按实际可见区域计算,而非固定值 |
| 收起键盘后页面错位 | 位移只加不减 | 补一个复原分支并做回归 |
结语
键盘遮挡不是单一缺陷,而是布局、系统回调、输入法行为三处叠加的结果。先靠录屏和布局边界把现象归类,再按端分别修,最后用一张验收表把机型与输入法拉齐,这类反馈会明显减少。
建议 团队把「键盘遮挡」单独列为内测回归项,每次改动表单页都跑一遍小屏机型加第三方输入法的组合,成本很低,但能挡住大部分上线后的投诉。