☰
uni-app 软键盘遮挡输入框:cursor-spacing 与 input 配置的 TaoToken 调试记录
2026/10/7 14:15:14 网站建设 项目流程

1. 聊天页底部输入框被软键盘顶歪的真实场景

先说我遇到的现象:一个 uni-app 做的聊天/评论页,底部固定一个输入框,点进去弹软键盘,输入框要么被键盘盖住一半,要么整个页面被顶上去、消息列表跟着乱跳,安卓和 iOS 表现还不一样。这个问题在 uni-app 里非常典型,核心关键词就是 uni-app 软键盘遮挡输入框、cursor-spacing 配置、uni-input 组件、input 事件处理。你如果正在搜「uni-app 底部输入框被软键盘挡住怎么办」,这篇就是我从排查到落地的完整记录。

先把结论摆前面:uni-app 的<input>和<textarea>组件自带cursor-spacing和adjust-position两个属性,前者控制光标与键盘的距离,后者控制键盘弹起时页面是否自动上推。绝大多数「被挡住」的情况,不是组件坏了,而是这两个参数没配对,或者外层容器用了position: fixed把自动上推的逻辑给废掉了。

适合谁看:正在做 uni-app 聊天页、评论页、客服对话页,底部输入框被软键盘遮挡,或者键盘弹起后页面跳动、输入框位置不对的同学。我会给出可复制的pages.json配置、组件写法、input 事件处理,最后演示怎么把请求 endpoint 改到 TaoToken 后,验证键盘弹起时输入框位置和接口调用是否都正常。

先理解一个类比:软键盘弹起时,浏览器/小程序容器会尝试把「当前聚焦的输入框」滚动到可视区域内。adjust-position就是这个自动滚动的开关,cursor-spacing则是告诉它「光标离键盘顶部留多少像素」。两个参数配合,才能让输入框稳稳停在键盘上方。很多人只加了cursor-spacing="0"就以为完事,结果外层fixed布局让自动滚动失效,问题依旧。

我试过的第一个坑:给输入框加了class="uni-input"和cursor-spacing="0",在 H5 上好了,一到微信小程序还是被挡。原因就是小程序端的adjust-position默认行为和外层fixed容器冲突。所以这篇不会只给你一行代码,而是把整套配置和验证流程讲清楚。

2. TaoToken 前置准备:把接口 endpoint 换成可调试的地址

排查软键盘问题的同时,我习惯把接口调用也一起验证,因为键盘弹起时如果接口报错,你很难分清是布局问题还是网络问题。这里用 TaoToken 作为统一的模型接口入口,把请求 endpoint 集中管理,方便在调试键盘时同步确认接口是否正常。

TaoToken 是什么、能做什么:它是一个兼容 OpenAI 风格接口的模型调用平台,你可以把它理解成「一个统一的 API 网关」,把模型对话、编码辅助等请求都发到同一个 Base URL,用同一套 Key 管理。适合谁:需要在前端项目里接入模型能力、又不想在多个厂商之间来回切换配置的开发者。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (这个不加 UTM)。

前置准备分三步,都很轻:

第一步,拿到 API Key。进入控制台创建密钥,路径是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面生成。生成后复制保存,后面配置里要用。密钥管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。

第二步,确认 Base URL 和 Model ID。Base URL 用 https://taotoken.net/api ,Model ID 按你实际要调的模型填,比如对话场景常用的模型标识。这两个值加上 Key,就是后面所有配置的「三件套」,缺一不可。

第三步,想先验证模型通不通,可以直接在模型对话页试一条消息,地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。如果对话能正常返回,说明 Key 和 Base URL 没问题,再回到前端排查键盘就少一个变量。

为什么要先做这步?因为软键盘弹起时,输入框的@confirm或@blur往往会触发一次接口请求。如果接口本身 401 或超时,你会看到「键盘弹起后输入框位置对了,但消息发不出去」,误以为是布局 bug。先把接口调通,排查范围就缩小到纯布局。

如果你后面要做长期编码或 Agent 类功能,可以了解下 Coding Plan,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,这里不展开,先把键盘问题解决。

3. 可复制配置:pages.json 与 input 组件完整写法

这一节是重点,直接给可复制的配置。先说pages.json,软键盘相关的页面级配置主要影响导航栏和页面滚动行为。对于聊天页这种底部固定输入框的场景,建议把页面样式设为自定义导航或至少确认app-plus下的软键盘模式。

{ "pages": [ { "path": "pages/chat/chat", "style": { "navigationBarTitleText": "聊天", "app-plus": { "softinputMode": "adjustResize", "softinputNavBar": "none" } } } ] }

这里的softinputMode设为adjustResize,意思是键盘弹起时调整页面大小而不是整体上推,配合底部固定输入框更稳。softinputNavBar设为none是为了避免安卓上键盘上方多出一条系统导航栏,把输入框又挤下去。

然后是组件写法。核心是<input>或<textarea>上的cursor-spacing和adjust-position:

<template> <view class="chat-page"> <scroll-view class="msg-list" scroll-y :scroll-top="scrollTop"> <view v-for="(msg, i) in messages" :key="i" class="msg-item"> {{ msg.content }} </view> </scroll-view> <view class="input-bar" :style="{ bottom: keyboardHeight + 'px' }"> <input class="uni-input" v-model="draft" cursor-spacing="20" :adjust-position="false" confirm-type="send" @focus="onFocus" @blur="onBlur" @confirm="onSend" placeholder="说点什么" /> <button size="mini" @click="onSend">发送</button> </view> </view> </template>

关键点解释:cursor-spacing="20"表示光标距离键盘顶部留 20px,值越大输入框离键盘越远。adjust-position设为false是因为我们自己用keyboardHeight控制输入框位置,避免系统自动上推和手动控制打架。confirm-type="send"让键盘右下角显示「发送」,配合@confirm触发发送。

对应的 script 部分,用uni.onKeyboardHeightChange监听键盘高度:

export default { data() { return { draft: '', messages: [], keyboardHeight: 0, scrollTop: 0 }; }, onLoad() { uni.onKeyboardHeightChange(res => { this.keyboardHeight = res.height; this.$nextTick(() => { this.scrollTop = 999999; }); }); }, methods: { onFocus() { this.scrollTop = 999999; }, onBlur() { this.keyboardHeight = 0; }, async onSend() { if (!this.draft.trim()) return; const text = this.draft; this.draft = ''; this.messages.push({ content: text }); await this.callModel(text); }, async callModel(text) { try { const res = await uni.request({ url: 'https://taotoken.net/api/v1/chat/completions', method: 'POST', header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer 你的_API_Key' }, data: { model: '你的_Model_ID', messages: [{ role: 'user', content: text }] } }); const reply = res.data.choices[0].message.content; this.messages.push({ content: reply }); this.scrollTop = 999999; } catch (e) { uni.showToast({ title: '请求失败', icon: 'none' }); } } } };

样式部分,输入栏用fixed定位,bottom由keyboardHeight动态控制:

.chat-page { display: flex; flex-direction: column; height: 100vh; } .msg-list { flex: 1; overflow: hidden; } .input-bar { position: fixed; left: 0; right: 0; bottom: 0; display: flex; align-items: center; padding: 10rpx 20rpx; background: #fff; border-top: 1rpx solid #eee; transition: bottom 0.15s; } .uni-input { flex: 1; height: 72rpx; padding: 0 20rpx; background: #f5f5f5; border-radius: 36rpx; }

这套配置的逻辑是:不用系统自动上推(adjust-position=false),而是自己监听键盘高度,把输入栏的bottom顶上去。这样在安卓和 iOS 上表现一致,也不会出现页面整体跳动。cursor-spacing保留一个正值,保证光标不贴键盘。

4. 验证请求:键盘弹起时输入框位置与接口调用是否正常

配置写完,必须验证两件事:一是键盘弹起时输入框位置对不对,二是接口调用是否正常返回。这一步很多人跳过,结果上线后才发现某个机型不对。

验证输入框位置:在真机上打开聊天页,点击输入框,观察键盘弹起后输入栏是否紧贴键盘上方。如果输入栏被键盘盖住,说明keyboardHeight没生效,检查uni.onKeyboardHeightChange是否在onLoad里注册、是否被其他逻辑覆盖。如果输入栏离键盘太远,把cursor-spacing调小,或者检查keyboardHeight是否多加了值。

验证接口调用:在输入框输入内容,点发送,看消息列表是否出现用户消息和模型回复。如果出现「请求失败」提示,先看控制台报错。常见的是 401,说明 Key 不对或没带Bearer前缀;如果是超时,检查 Base URL 是否写成了https://taotoken.net/api而不是带/v1的完整路径。

我实测下来,把 endpoint 改到 TaoToken 后,键盘弹起时输入框位置稳定,接口也能正常返回。这里有个细节:uni.request在键盘弹起状态下发起请求,如果页面被键盘顶动,回调里的this可能指向变化,所以我在callModel里用箭头函数或提前保存this,避免this.messages报 undefined。

再给一个验证清单,你可以照着过一遍:

检查项预期结果不对时看哪里
键盘弹起输入框位置紧贴键盘上方keyboardHeight 监听
光标与键盘距离约 20pxcursor-spacing 值
发送后接口返回有模型回复Key / Base URL / Model ID
消息列表滚动自动滚到底部scrollTop 赋值时机
键盘收起输入栏回到底部onBlur 重置 keyboardHeight

如果接口返回正常但消息列表没更新,多半是scrollTop赋值时机太早,用$nextTick包一层。如果键盘收起后输入栏没回到底部,检查onBlur里有没有把keyboardHeight重置为 0。

想单独验证模型是否可用,可以到模型对话页发一条消息,地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。如果那里正常,前端还报错,问题就在前端配置而不是接口。

5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth

这一节把真实会遇到的报错列出来,对照排查。软键盘问题往往和接口报错混在一起,分清楚才能快速定位。

401 Unauthorized:最常见。原因通常是 Key 没填、填错、或者Authorization头没带Bearer前缀。检查header里是不是'Authorization': 'Bearer 你的_API_Key',注意 Bearer 后面有一个空格。如果 Key 是从控制台复制的,确认没有多余换行。密钥管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,可以重新生成一个再试。

local proxy failed:这个报错通常出现在本地开发环境,说明请求没发出去就被本地代理拦了。检查你的开发工具是否开了代理设置,或者uni.request的域名白名单是否包含taotoken.net。小程序端需要在后台配置 request 合法域名,把https://taotoken.net加进去。H5 端如果本地起了 devServer proxy,确认代理规则没把/api转发到错误地址。

reading 'choices':报错类似Cannot read property 'choices' of undefined,说明返回结构里没有choices字段。原因可能是接口返回了错误信息而不是正常结果,比如res.data.error。先打印res.data看完整结构,确认是不是 401 或参数错误。也可能是 Model ID 填错,导致接口返回错误对象。确认 Model ID 和 Base URL 匹配。

OAuth 相关报错:如果你用了某些需要 OAuth 授权的客户端或插件,报错可能提示 token 过期或授权失败。这类问题不在软键盘本身,而是认证链路。检查你的客户端配置里 Base URL 是否指向https://taotoken.net/api,Key 是否有效。如果是 Claude Code 这类工具,配置里通常需要填 Base URL、Key、Model ID 三件套,缺一个都会报认证错。

再补充几个软键盘相关的坑:

一是外层容器用了position: fixed且高度写死,导致adjust-position自动上推失效。解决办法就是本文的手动keyboardHeight方案。

二是cursor-spacing设得太大,输入框离键盘很远,用户以为没弹键盘。一般 10 到 30 之间比较合适。

三是@confirm和@blur同时触发发送,导致重复请求。可以在onSend里加一个sending标志位,发送中忽略重复调用。

四是安卓上键盘弹起时页面resize触发多次,keyboardHeight抖动。可以在监听里做防抖,或者只在高度变化超过阈值时更新。

排查顺序建议:先看控制台报错定位是接口还是布局,接口问题按上面四类对号入座,布局问题回到第 3 节的配置逐项核对。接口调通了,再调键盘,效率最高。

6. 把调试流程固定下来:接入文档与后续验证入口

软键盘遮挡这个问题,本质是「系统自动行为」和「自定义布局」的协调。我的经验是:不要依赖系统自动上推,而是自己监听键盘高度、手动控制输入栏位置,这样跨端表现最一致。cursor-spacing负责光标距离,adjust-position负责是否自动上推,uni.onKeyboardHeightChange负责拿到键盘高度,三者配合就够用了。

接口这边,把 Base URL 统一成https://taotoken.net/api,Key 和 Model ID 集中配置,调试键盘时同步验证接口,能省很多来回。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有完整的接口说明和参数示例,遇到不确定的字段可以对照。

如果你要验证模型对话是否正常,直接用模型对话页发一条消息最快,地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。长期做编码或 Agent 类功能,可以看 Coding Plan,地址是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。

最后留一个实用技巧:把keyboardHeight的监听和输入栏的bottom绑定写成一个可复用组件,聊天页、评论页、客服页都能直接用。这样下次再遇到软键盘遮挡,你只需要引入组件、传一个发送回调,不用重新调一遍参数。接口的 Key 和 Base URL 也建议抽到一个配置文件里,换环境时只改一处,避免在多个页面里散落硬编码。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询