应设为adjustPan:它不压缩WebView高度,而是整体上推页面,消除挤压感;仅对App平台生效,需在pages.json对应页面style的app-plus下配置,且显式声明更可控。

pages.json 里 softinputMode 设成 adjustPan 才能取消挤压
页面被“挤压”是 adjustResize 模式下的正常表现,不是 bug。你想取消挤压,就得主动退回到系统默认的 adjustPan 模式——它不会压缩 WebView 高度,而是把整个页面像纸片一样往上托,视觉上没挤压感,但布局会偏移。
这个配置只对 App 平台(iOS/Android)生效,必须写在对应页面的 pages.json 的 style.app-plus 下:
"app-plus": {
"softinputMode": "adjustPan"
}
注意:adjustPan 是 App 端默认值,不配也生效;但显式写出更可控,避免被全局配置覆盖。
- 别在 H5 或小程序里折腾这个字段——它们根本不读
softinputMode - 如果用了
scroll-view或自定义滚动容器,adjustPan可能导致内部滚动错乱,得额外监听uni.onKeyboardHeightChange做补偿 - 设了
adjustPan后,textarea的adjust-position属性就失效了,它只在adjustResize下起作用
adjust-position="false" 在 H5 下完全无效
H5 平台压根不支持 adjust-position,无论设成 true 还是 false,都不会影响键盘行为。你看到的“页面上移”,其实是 Android WebView 触发 resize 事件后,window.innerHeight 缩小导致的 fixed 元素位置漂移。
真正在 H5 起作用的是 uni.onWindowResize:
- 用它监听视口高度变化,算出键盘高度差(原始高度 − 当前
res.size.windowHeight) - 聚焦时加
setTimeout延迟 50ms 再取高度,否则首次触发时值不准 - 失焦后不能立刻还原 bottom/padding,得等键盘收起动画完成(通常
setTimeout(() => {}, 150))
为什么监听 keyboardHeightChange 还是会被顶飞
因为 uni.onKeyboardHeightChange 在 iOS 上可能返回不稳定的 height:键盘收起时先报 0,再报一个残留高度(比如 20px),导致底部区域闪一下又下坠。
更稳妥的做法是结合状态机控制:
- 只在
height > 100时才认为键盘真正弹出(过滤误报) - 用
onFocus记录当前输入框 DOM 节点,onBlur时清空,避免多个 input 共享同一高度状态 -
onUnload里必须调uni.offKeyboardHeightChange,否则监听器残留会跨页污染
fixed 元素被顶到半空,别修 CSS,要换定位逻辑
在 adjustPan 模式下,position: fixed 不可靠——它被系统强制“锚定”在 WebView 底部,而 WebView 自己上移了,所以元素看起来飘在屏幕中间。
替代方案更有效:
- 把底部输入栏从
fixed改成absolute,父容器设position: relative,再用padding-bottom动态预留键盘高度 - 用 flex 布局:父容器
display: flex; flex-direction: column;,内容区flex: 1,底部区域固定高度,天然避开键盘挤压逻辑 - nvue 页面不支持
uni.onKeyboardHeightChange,得用 bindingX 或原生模块监听,普通 Vue 方案在这里直接失效
最常被忽略的一点:所有监听都必须配节流(比如 100ms),否则键盘横竖屏切换、快速收起再弹出时,回调高频触发会导致样式抖动或滚动错位。


















