微信小程序 input 被键盘盖住:cursor-spacing 与 adjust-position 的 TaoToken 调试配置 1. 底部 input 被键盘顶飞的现场还原微信小程序里做聊天页或者底部表单页最容易翻车的地方就是那个贴着屏幕底边的input。页面在浏览器模拟器里看着一切正常点一下输入框光标闪得挺欢可一旦上真机软键盘唰地弹起来输入框要么被整个盖住要么只露出半截用户根本看不见自己打了什么字。这个问题的核心检索词就是微信小程序 input 被键盘盖住而解决它的关键参数就是cursor-spacing和adjust-position。先说清楚这两个属性到底管什么。adjust-position是布尔值默认true意思是键盘弹起时页面自动往上推保证输入框可见。cursor-spacing是数字单位 px指定光标和键盘顶部之间要留多少距离。很多人以为设了adjust-positiontrue就万事大吉结果发现页面是推上去了但输入框紧贴着键盘边缘视觉上还是糊在一起体验很差。这时候就需要cursor-spacing来补一刀把间距撑开。这个场景适合谁适合所有在做聊天、评论、客服、下单备注这类底部固定输入栏的开发者。尤其是用position: fixed; bottom: 0布局的同学几乎百分百会踩这个坑。因为 fixed 定位的元素不参与页面文档流键盘弹起时系统推的是页面滚动fixed 元素的行为在不同机型上表现不一致iOS 和 Android 的差异尤其明显。我试过在一个聊天页里输入框用 fixed 固定在底部adjust-position默认开着iOS 上表现还行但 Android 某些机型上输入框直接被键盘盖住用户得手动往上滑才能看到。后来把cursor-spacing加上再配合键盘高度监听动态调整才彻底稳住。下面我把整个排查和配置过程拆开讲你可以直接照着改。在动手之前先明确一个排查顺序先看adjust-position有没有被误关再看cursor-spacing设了没最后看需不需要监听键盘高度做动态补偿。这三步基本能覆盖 90% 的遮挡问题。接下来我会先讲怎么准备调试环境再给可复制的配置片段然后上真机验证。2. 用 TaoToken 准备调试与联调环境在正式改代码之前我习惯先把调试和联调的链路搭好。因为小程序开发经常需要一边看真机表现一边对照接口返回、日志和模型输出尤其是当你的输入框还要对接后端接口或者 AI 对话能力时一个稳定的调试入口能省很多事。这里我用 TaoToken 来做接口联调和模型对话验证它的 API 入口是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。为什么调试输入框遮挡还要扯到接口平台因为实际项目里输入框提交后往往要调后端。如果后端接口本身不稳定你会分不清输入框被盖住和请求失败哪个才是真问题。把接口链路先跑通排障时变量就少一个。TaoToken 在这里的角色是提供一个统一的模型调用入口你可以用它来验证输入内容提交后的处理逻辑比如把用户输入发给模型做意图识别看返回是否正常。具体操作上先去控制台创建一个 API Key。打开https://taotoken.net/console登录后在 API Keys 页面新建一个密钥复制保存好。这个 Key 后面会用在请求头里。注意不要把它硬编码到小程序前端代码里小程序的前端代码是可以被反编译的Key 泄露风险很高。正确做法是把 Key 放在你自己的后端服务里小程序只调你的后端后端再转发到 TaoToken。如果你只是想快速验证模型对话效果可以直接用模型对话页面https://taotoken.net/model-chat在里面输入测试文本看返回是否符合预期。这个页面适合调 prompt 和验证模型能力不需要写代码。等你确认模型输出没问题再把它接到后端接口里。对于需要长期做编码和 Agent 开发的场景可以了解下 Coding Plan入口在https://taotoken.net/coding-plan。它适合那种需要反复调用模型、做代码生成或者自动化任务的开发者。不过对于本文的输入框遮挡问题你其实用不到这么重的配置一个 API Key 加一个模型对话验证就够了。接入文档在https://taotoken.net/doc里面有完整的请求示例和参数说明。我建议你在改小程序代码之前先花十分钟把文档里的快速开始跑一遍确认你的网络环境能正常访问 API。这一步看起来和输入框无关但它能帮你排除到底是前端布局问题还是后端请求问题的干扰。环境准备好之后我们进入正题。下面先给可复制的配置片段包括page.json和input属性然后讲每个参数为什么这么设。3. 可复制的 page.json 与 input 配置片段先看页面结构。假设你有一个聊天页pages/chat/chat底部是固定输入栏。page.json里主要控制页面样式和导航栏真正影响键盘行为的是input组件本身的属性。不过page.json里可以配置disableScroll之类的选项来辅助控制滚动行为所以我一并给出。page.json配置如下{ navigationBarTitleText: 聊天, disableScroll: false, usingComponents: {} }这里disableScroll设为false允许页面滚动。有些同学为了防穿透把它设成true结果键盘弹起时页面无法滚动输入框反而更容易被盖住。除非你有明确的防穿透需求否则保持false。接下来是核心的input配置。在chat.wxml里view classinput-bar input classmsg-input typetext value{{inputValue}} placeholder请输入内容 confirm-typesend adjust-position{{true}} cursor-spacing20 bindinputonInput bindconfirmonSend bindfocusonFocus bindbluronBlur / /view对应的chat.wxss.input-bar { position: fixed; left: 0; right: 0; bottom: 0; padding: 16rpx 24rpx; background: #ffffff; box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06); z-index: 100; } .msg-input { height: 72rpx; line-height: 72rpx; padding: 0 24rpx; background: #f5f5f5; border-radius: 36rpx; font-size: 28rpx; }关键参数说明用表格对照更清楚属性取值作用建议adjust-positiontrue/false键盘弹起时是否自动上推页面保持true除非自己接管cursor-spacing数字单位 px光标与键盘顶部的距离设 20 到 100视 UI 而定confirm-typesend/done等键盘右下角按钮文案聊天页用sendhold-keyboardtrue/false点击页面是否保持键盘默认false即可cursor-spacing的取值逻辑要理解清楚系统会取input 距离页面底部的距离和cursor-spacing指定值两者中的最小值作为光标与键盘的距离。也就是说如果你的 input 本身离底部很近cursor-spacing设再大也没用因为取的是最小值。这就是为什么光设cursor-spacing有时不生效——input 离底部太近了。解决办法是给 input 外面包一层有底部内边距的容器或者用padding-bottom把 input 往上抬一点。比如上面的.input-bar加了padding: 16rpx 24rpxinput 距离屏幕底部就有了 16rpx 的缓冲cursor-spacing再设 20px实际间距就会更合理。如果你需要更精细的控制比如键盘弹起时动态调整输入栏位置就需要监听键盘高度。微信小程序提供了wx.onKeyboardHeightChange接口Page({ data: { inputValue: , keyboardHeight: 0 }, onLoad() { this.keyboardHandler (res) { this.setData({ keyboardHeight: res.height }); }; wx.onKeyboardHeightChange(this.keyboardHandler); }, onUnload() { wx.offKeyboardHeightChange(this.keyboardHandler); }, onInput(e) { this.setData({ inputValue: e.detail.value }); }, onSend() { const text this.data.inputValue.trim(); if (!text) return; console.log(发送内容:, text); this.setData({ inputValue: }); } });拿到keyboardHeight后你可以动态设置输入栏的bottom值让它在键盘上方固定。不过大多数情况下adjust-position加cursor-spacing已经够用动态监听是给那些 fixed 布局在 Android 上表现异常的机型兜底的。配置写完后别急着上真机先在开发者工具里点一下输入框看模拟键盘弹起时页面有没有上推。工具里的表现和真机有差异但至少能确认属性写对了。接下来进入真机验证环节。4. 真机验证iOS 与 Android 间距实测真机验证是这一步的重头戏因为 iOS 和 Android 对键盘的处理机制完全不同。iOS 的键盘弹起是系统级的页面推举比较平滑Android 则因厂商定制差异很大有的推页面有的直接覆盖还有的会改变窗口高度。所以同一套配置两个平台表现可能天差地别。验证步骤我分成四步你可以照着做。第一步准备两台设备一台 iOS一台 Android。iOS 建议用较新系统版本Android 尽量覆盖一个原生系统和一个定制系统比如小米、华为各一台。如果手头设备有限至少保证两个平台各测一台。第二步在 iOS 上打开小程序聊天页点击底部 input。观察三件事输入框是否可见、光标与键盘顶部之间有没有间距、页面是否被推得过高导致顶部内容消失。正常情况下adjust-positiontrue会让页面整体上推input 停在键盘上方cursor-spacing20会让光标和键盘之间留出约 20px 的视觉间距。如果输入框紧贴键盘说明cursor-spacing没生效检查 input 距离底部的距离是不是小于 20px。第三步在 Android 上重复同样操作。Android 上重点看输入框有没有被完全盖住。有些 Android 机型在adjust-positiontrue时不会推页面而是把键盘覆盖在页面上这时候 input 就被盖住了。解决办法是监听keyboardHeight动态把输入栏的bottom设为键盘高度// 在 onKeyboardHeightChange 回调里 this.setData({ keyboardHeight: res.height, inputBarBottom: res.height });然后在 wxml 里绑定样式view classinput-bar stylebottom: {{inputBarBottom}}px;注意如果你用了动态bottom就要把adjust-position设为false否则系统推举和你的动态调整会打架页面会跳来跳去。第四步记录两个平台的实测结果。我实测下来iOS 上adjust-positiontrue加cursor-spacing20基本能解决遮挡输入框稳稳停在键盘上方。Android 原生系统表现接近 iOS但部分定制系统需要动态监听键盘高度才能彻底消除遮挡。测试时还要注意横竖屏切换横屏下键盘高度变化更大遮挡问题更容易出现。验证通过的标准很简单点击 input键盘弹起输入框完整可见光标和键盘之间有舒适间距页面没有异常跳动。三个条件都满足就算搞定。如果你在验证过程中发现输入框还是被盖住别急下一节我把常见报错和排查方法列出来。5. 常见报错与排查从 401 到 local proxy failed排查输入框遮挡时你可能会遇到一些看起来不相关的报错比如接口 401、local proxy failed、reading choices之类的。这些报错和键盘遮挡本身没关系但它们会干扰你的判断让你误以为是布局问题。我把常见的几类列出来对照排查。第一类接口 401。这通常是你调 TaoToken API 时 Key 没带对或者过期了。检查请求头里的Authorization字段格式是Bearer 你的Key。如果你在小程序前端直接调 API还要注意小程序的request合法域名配置没配的话请求会被拦截表现可能是请求失败而不是 401。正确做法是后端转发前端只调自己的后端。第二类local proxy failed。这个报错一般出现在你本地起了代理服务做转发但代理没启动或者端口不对。排查时先确认代理进程在跑再确认小程序请求的地址和代理端口一致。如果你用的是 TaoToken 的 API 入口https://taotoken.net/api确认网络能正常访问可以用 curl 先测一下curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer 你的Key \ -H Content-Type: application/json \ -d {model:你的模型ID,messages:[{role:user,content:test}]}返回正常 JSON 说明链路通返回错误就看错误信息定位。第三类reading choices。这是解析响应时choices字段不存在导致的通常是因为请求失败返回了错误结构但代码直接去读data.choices[0]。加个判断if (res.data res.data.choices res.data.choices.length 0) { const reply res.data.choices[0].message.content; } else { console.error(响应结构异常:, res.data); }第四类OAuth 相关报错。如果你用了需要 OAuth 授权的模型服务token 过期会报这个。重新走一遍授权流程拿到新 token 再试。第五类也是和本文最相关的输入框配置写了但没生效。排查顺序是先确认adjust-position没被设成false再确认cursor-spacing的值和 input 距底部距离的关系最后确认有没有其他样式比如position: absolute或父容器overflow: hidden干扰。有个隐蔽的坑是父容器设了overflow: hidden键盘弹起时页面推举被裁剪输入框看起来没动。如果你在配置里用到了 CC Switch、Cline MCP 或者 Codex 的auth.json记得三件套要写全Base URL、Key、Model ID。缺一个都会导致请求失败而请求失败又容易和布局问题混淆。Base URL 用https://taotoken.net/apiKey 用你控制台生成的Model ID 按文档填。排查时建议开两个窗口一个看小程序真机日志一个看后端请求日志。这样能快速区分是前端布局问题还是后端接口问题。大部分遮挡问题都是前端配置问题把cursor-spacing和adjust-position调对再配合键盘高度监听基本都能解决。6. 继续联调与模型验证的入口输入框遮挡解决之后下一步通常是把用户输入接到后端做处理。如果你需要验证模型对用户输入的理解能力可以用模型对话页面快速测试入口在https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite。在里面输入几段典型用户消息看模型返回是否符合预期确认后再接到小程序后端。如果你在做的是长期编码项目需要反复调用模型做代码生成或自动化任务可以看下 Coding Plan入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite。它适合那种调用量大、需要稳定配额的场景。API Key 的管理在控制台入口是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite。建议给不同项目建不同的 Key方便排查和限额。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面有完整的参数说明和示例代码遇到请求格式问题先翻文档。最后提醒一句小程序前端千万不要硬编码 API Key。正确链路是小程序调你的后端后端持有 Key 并转发到 TaoToken。这样既安全也方便你在后端做日志和限流。输入框遮挡是前端布局问题接口联调是后端链路问题两者分开排查效率会高很多。