uni.onkeyboardheightchange仅app端生效,需在onready注册并配对清理;web-view需动态调整height和top;安卓需扣除虚拟键高度;textarea需设置cursor-spacing且pages.json配置softinputmode。

uni.onKeyboardHeightChange监听不到?检查平台和生命周期
这个 API 只在 App 端(iOS / Android)生效,H5 和小程序里根本不会触发回调,直接写死监听等于白忙。如果你在 H5 调试时发现 uni.onKeyboardHeightChange 完全没反应,不是代码错了,是平台不支持——得加条件编译或 fallback 逻辑。
监听必须在页面真正就绪后注册,否则可能错过首次键盘弹起事件。推荐在 onReady 里调用,而不是 onLoad 或 mounted(尤其 Vue3 setup 中未等 DOM 挂载完就注册容易失效)。
别忘了配对清理:在 onUnload 或 beforeUnmount 中执行 uni.offKeyboardHeightChange,否则页面跳走后监听还在,会持续占用内存、甚至影响其他页面的键盘回调。
web-view 内评论框被遮挡?不能只靠 H5 自己滚动
web-view 是原生容器,内部 H5 页面的 focus 或 scrollIntoView 在 App 端常常无效,尤其是 iOS。你看到输入框没动,不是 JS 没执行,而是 web-view 的 viewport 高度没变,系统根本不给它重绘机会。
真正有效的解法是动态改 webview-styles.height:键盘弹起时设为 calc(100vh - ${keyboardHeight}px) 或直接赋值计算后的像素数;收起时还原为 '100%' 或 ''(空字符串表示恢复默认高度)。
注意 top 偏移要同步处理:如果页面有状态栏或自定义导航栏,webview-styles.top 必须包含 statusBarHeight,否则高度重算后 web-view 会上移错位。
底部评论工具栏定位不准?得减掉虚拟导航键高度
安卓很多机型底部有虚拟按键(比如华为、小米的返回/主页键),这部分高度会被计入 screenHeight,但不参与实际布局,导致 uni.onKeyboardHeightChange 返回的 height 比真实键盘高一截。
真实可用键盘高度 = res.height - (screenHeight - windowHeight),其中 screenHeight 和 windowHeight 来自 uni.getSystemInfoSync()。
这个差值在 iPhone 上基本为 0,但在安卓上普遍是 48~120px。不扣掉的话,你的评论工具栏会悬在键盘上方一段空白里,用户点不到按钮。
另外,res.height 在键盘收起瞬间可能为 0,做减法前务必判断:this.keyboardHeight = Math.max(0, res.height - virtualKeyHeight)。
adjust-position 设为 false 后,textarea 位置还是乱?cursor-spacing 是关键
adjust-position="false" 关闭自动上推后,textarea 不再随键盘移动,但它的光标位置会影响软键盘与输入框的相对关系。如果没设 cursor-spacing,光标可能贴着键盘顶边,导致最后一行文字被遮住一半。
建议显式设置 cursor-spacing="40"(单位 px),数值根据输入框距底部距离微调,一般 30~60 范围内较稳。
iOS 对 cursor-spacing 更敏感,Android 则更依赖 softinputMode 配置。pages.json 中对应页面的 "app-plus": {"softinputMode": "adjustResize"} 必须加上,否则即使 JS 层做了高度计算,原生层也不响应布局收缩。
真实场景里最易忽略的是:安卓虚拟键高度要实时算、iOS 的 webview-styles.height 设空字符串比设 '100%' 更可靠、以及 pages.json 里漏配 softinputMode 会让所有 JS 动态调整失效。这三处不处理,其余逻辑再精细也没用。











