1. 小程序 iOS 软键盘弹起挡住 input 输入框:用 onKeyboardHeightChange 做精准避让
小程序在 iOS 真机上,软键盘弹起遮挡 input 输入框是个老生常谈的问题。你可能会发现,安卓上跑得好好的页面,一到 iOS 就翻车:输入框被键盘顶到屏幕外,或者页面整体上推后底部留出一大块空白,键盘收起后布局又回不到原位。这个问题的核心在于 iOS 的键盘处理机制和安卓差异很大,微信小程序默认的adjust-position自动上推策略在 iOS 上经常出现错位。onKeyboardHeightChange就是官方给出的解法——它能实时告诉你键盘弹起了多高,你拿着这个高度自己去控制输入框容器的位置,避让逻辑完全掌握在自己手里。这篇内容适合正在做小程序表单、聊天输入框、评论区的开发者,尤其是被 iOS 真机键盘问题折磨过的朋友。下面我会从问题复现讲起,给出可复制的页面配置和监听代码骨架,再说明怎么在真机上验证避让生效、键盘收起后布局复位。
2. 先搞清楚 iOS 上 input 被挡住的真实原因
2.1 默认 adjust-position 在 iOS 上的表现
小程序 input 组件有个属性叫adjust-position,默认值是true,意思是键盘弹起时页面自动上推。这个机制在安卓上基本够用,但在 iOS 上,页面整体上推后,如果输入框本身靠近底部,或者页面有固定定位的容器,就会出现两种典型错位:一种是输入框被推到键盘上方后,光标位置和视觉位置对不上;另一种是键盘收起时页面没有完全回弹,底部残留一段空白。
我试过在一个聊天页面里用cursor-spacing去控制光标和键盘的距离,安卓上没问题,iOS 上直接错位。后来才转向onKeyboardHeightChange手动控制。
2.2 为什么需要手动监听键盘高度
onKeyboardHeightChange是uni或wx提供的全局回调,键盘弹起和收起时都会触发,回调参数里的res.height就是当前键盘的高度(单位 px)。拿到这个值后,你可以把它赋给输入框容器的bottom样式,让容器始终贴在键盘上方。这样做的好处是避让逻辑完全由你控制,不依赖系统的自动上推,iOS 和安卓表现一致。
关键点在于:input 组件上要加:adjust-position="false",关掉系统自动上推,否则系统上推和你的手动避让会打架,错位更严重。
3. 前置准备:TaoToken 接入与页面基础配置
在动手改代码之前,如果你打算把输入框的交互逻辑接到大模型对话能力上(比如做一个 AI 聊天输入框),可以先把 TaoToken 的接入准备好。TaoToken 是一个大模型 API 聚合平台,官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。它支持模型对话、Coding Plan、控制台管理、API Keys 等能力,适合做小程序里的 AI 输入场景。
3.1 获取 API Key
进入控制台后创建 API Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。拿到 Key 后,你可以在小程序的云函数或后端服务里调用模型对话接口,地址是 https://taotoken.net/api 。如果你只是做纯前端避让,这一步可以跳过,直接看第 4 节的代码。
3.2 页面结构规划
避让的核心思路是:给 input 外面套一个容器,容器用fixed或relative定位,动态设置bottom值。input 本身加:adjust-position="false"。页面 data 里维护一个inputHeight,初始为null或0。
4. 可复制的配置与监听代码骨架
4.1 模板结构
<template> <view class="chat-page"> <!-- 消息列表 --> <scroll-view class="msg-list" scroll-y> <!-- 消息内容 --> </scroll-view> <!-- 输入框容器,动态 bottom --> <view class="input-bar" :style="{ bottom: inputHeight - 1 + 'px' }"> <input type="text" placeholder="你得说点什么.." :focus="focus" :adjust-position="false" @blur="onBlur" v-model="inputValue" /> </view> </view> </template>注意bottom那里减了 1px,这是 iOS 上的经验值,不减的话输入框和键盘之间会有一条细缝。
4.2 样式配置
.chat-page { position: relative; height: 100vh; overflow: hidden; } .msg-list { height: 100%; padding-bottom: 100rpx; } .input-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 20rpx; background: #fff; border-top: 1rpx solid #eee; transition: bottom 0.2s; }容器用fixed定位,bottom由inputHeight驱动。加个transition让避让过程平滑一点。
4.3 监听键盘高度变化
export default { data() { return { inputHeight: 0, focus: false, inputValue: '' }; }, onLoad() { this.initKeyboardListener(); }, onUnload() { uni.offKeyboardHeightChange(); }, methods: { initKeyboardListener() { uni.offKeyboardHeightChange(); uni.onKeyboardHeightChange(res => { this.inputHeight = res.height; }); }, onBlur() { // 安卓上键盘收起时 height 可能不归零,手动复位 this.inputHeight = 0; } } };这里有几个细节要说明。第一,onLoad里先offKeyboardHeightChange再on,避免页面多次进入时重复注册。第二,onUnload里注销监听,防止内存泄漏。第三,onBlur里把inputHeight重置为 0,这是针对安卓的兜底——安卓上键盘收起时res.height有时不会变成 0,导致输入框悬在半空。
4.4 参数对照表
| 参数/属性 | 作用 | 推荐值 |
|---|---|---|
adjust-position | 键盘弹起是否自动上推页面 | false |
inputHeight | 键盘高度,驱动容器 bottom | 初始 0 |
bottom偏移 | iOS 上避免细缝 | inputHeight - 1 |
onBlur复位 | 安卓键盘收起兜底 | inputHeight = 0 |
offKeyboardHeightChange | 注销监听 | onUnload 调用 |
5. 验证请求与真机调试结果
5.1 真机验证步骤
代码写完后,在微信开发者工具里点「真机调试」,用 iOS 手机扫码。打开页面后点击输入框,观察三件事:键盘弹起时输入框是否紧贴键盘上方、输入框是否完整可见、键盘收起后输入框是否回到屏幕底部。
如果输入框紧贴键盘且没有细缝,说明bottom: inputHeight - 1生效了。如果键盘收起后输入框回到原位,说明onBlur复位逻辑正常。
5.2 接入模型对话验证
如果你把输入框接到了 TaoToken 的模型对话能力上,可以在输入框里发一条消息,看请求是否正常返回。模型对话入口是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite ,你可以在那里先测试接口连通性。小程序端调用时,把 API Key 放在后端或云函数里,不要直接暴露在前端代码中。
5.3 成功结果说明
避让生效的表现是:iOS 真机上键盘弹起,输入框容器 bottom 值等于键盘高度减 1,输入框完整显示在键盘上方;键盘收起,onKeyboardHeightChange触发res.height为 0,容器 bottom 回到 0,输入框回到屏幕底部。整个过程没有页面整体上推,也没有底部空白残留。
6. 本篇常见错排查
6.1 输入框和键盘之间有条缝
这是 iOS 上的典型问题,原因是bottom值没有减 1px。把inputHeight - 1改成inputHeight - 1即可。如果减 1 还不够,可以试减 2,不同机型可能有细微差异。
6.2 键盘收起后输入框悬在半空
这是安卓上的常见问题,res.height在键盘收起时没有归零。解决办法就是在 input 上加@blur事件,失焦时把inputHeight重置为 0。注意blur和键盘收起不一定完全同步,但实际表现足够用。
6.3 页面整体还是被上推了
检查 input 上是否加了:adjust-position="false"。如果没加,系统自动上推和你的手动避让会同时生效,页面会被推两次,错位更严重。
6.4 监听重复触发或页面卡顿
检查onLoad里是否先调了offKeyboardHeightChange。如果页面多次进入而没有注销旧监听,会累积多个回调,导致inputHeight被反复赋值,页面抖动。onUnload里也要记得注销。
6.5 输入框被键盘挡住但 bottom 没变
确认onKeyboardHeightChange是否真的触发了。可以在回调里加console.log(res.height),真机调试时看控制台输出。如果没输出,检查uni或wx对象是否正确引入,以及基础库版本是否支持该 API。
7. 语义一致 CTA
避让逻辑调通后,如果你要把输入框接到大模型对话、Coding Plan 或 Agent 场景,建议先把 API Key 和接入文档过一遍。API Keys 管理在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。长期做编码或 Agent 的,可以看 Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。ClaudeCodeAnthropic 相关入口在 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 。模型对话测试用 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。