adjust-position="true"是解决App端键盘遮挡的必要开关,仅对原生input/textarea生效,需配合pages.json中softinputMode:"adjustResize"及cursor-spacing:80–120使用,三者缺一不可。

input 的 adjust-position 属性为什么必须设为 true
这是解决遮挡问题的底层开关,不是可选项。uni-app 在 App 端(尤其是 Android)默认会关闭自动调整,导致键盘一弹,页面纹丝不动,底部按钮直接被盖住。adjust-position="true" 告诉框架:“别傻站着,键盘来了你就动”。但注意:它只在原生 或 上生效,u-input、uni-data-picker 等封装组件内部可能绕过或忽略该属性。
常见错误现象:
- 加了
adjust-position="true"却没效果 → 很可能你用的是u-input,它压根不透传这个 prop - iOS 上有效,Android 上无效 → 检查是否同时漏掉了
always-embed="true"(Android 需强制嵌入键盘上下文)
pages.json 里 softinputMode 怎么配才不翻车
这个配置是 App 端的“系统级行为开关”,作用于整个 WebView 容器,比组件级属性更底层。不配它,adjust-position 就像没装发动机的车——看着有轮子,跑不起来。
实操建议:
- 在对应页面的
pages.json中添加:"app-plus": { "softinputMode": "adjustResize" } - 别用
adjustPan:它只会平移内容,不重排布局,遮挡依旧;adjustResize才会让 WebView 高度随键盘收缩,触发真实滚动 - 仅对 App 生效,H5 和小程序无需也不支持此配置
为什么光靠监听 keyboardHeightChange 动态改 bottom 很容易出错
手动监听高度再改样式,看似灵活,实则踩中三个硬伤:时机不可控、状态难同步、兼容性差。比如 iOS 键盘收起时 height 可能先报 0 再报真实值,导致按钮闪一下又掉回去;Android 某些输入法(如搜狗)甚至不触发该事件。
典型翻车场景:
- 用
@focus里直接取e.detail.height→ 这个值在首次 focus 时经常是0或不准,尤其在冷启动页面 - 多个 input 共享同一个
keyboardHeightdata 字段 → 切换焦点时旧高度未清,新输入框被顶高或压低 - 没调
uni.offKeyboardHeightChange()→ 页面销毁后监听还在,引发内存泄漏和跨页干扰
cursor-spacing 设多少才靠谱
它不是“留白越多越好”,而是要匹配真实键盘高度的视觉节奏。设太小(如 20),光标紧贴键盘,用户看不清输入内容;设太大(如 300),页面猛地上蹿,体验割裂。实测下来,80–120 是最稳区间,尤其在全面屏手机上。
关键细节:
- 单位是
rpx,不是px或vh,确保跨设备缩放一致 - 必须配合
adjust-position="true"使用,单独设无效 - 在密码输入框上尤其重要——用户无法实时看到明文,光标位置就是唯一反馈依据
实际项目里最容易被忽略的,是把 adjust-position、softinputMode、cursor-spacing 当成“三选一”来试。它们是同一链条上的三颗螺丝:缺一不可,拧得松紧也得匹配。漏掉任意一个,遮挡就可能在某台真机上突然重现。











