用途
capacitor-keyboard 用于修复 Capacitor 应用中屏幕键盘(on-screen keyboard)的行为问题。当出现以下情况时可参考本技能:聚焦的输入框被键盘遮挡或页面意外滚动;聊天输入框 / 固定页脚不贴合键盘;键盘上方出现白色或黑色条带(Android 15+ 边到边、iOS 背景);键盘打开时 100vh / dvh 布局塌陷;iOS 聚焦输入框时缩放,或 QuickType / 辅助栏显示异常;键盘事件不触发或触发两次。
不适用场景:刘海 / home 指示条 / 状态栏内边距(应使用 safe-area-handling);Ionic ion-input、ion-footer 样式(应使用 ionic-design);标签、焦点顺序、屏幕阅读器(应使用 capacitor-accessibility)。
平台模型(关键决策)
iOS 与 Android 的键盘处理机制不同:
- iOS:由插件按 resize 模式调整尺寸;事件 keyboardWillShow 在动画前触发,keyboardDidShow 在动画后触发;JS 控制包括 setResizeMode、getResizeMode、setScroll、setStyle、setAccessoryBarVisible(仅 iPhone)、show()(仅 Android)、hide()。
- Android:由操作系统 + WebView 调整尺寸,resize 配置被忽略;Will/Did 事件几乎同时触发。
iOS resize 模式(KeyboardResize 枚举):
- native(默认):整个 WebView 缩小,vh 单位随之变化。适用于普通 Web 应用,最简单。
- body:仅 <body> 高度变化,vh 不变。适用于依赖稳定 vh 的布局。
- ionic:仅 ion-app 调整尺寸。仅适用于 Ionic Framework 应用。
- none:不调整任何尺寸,由开发者根据键盘高度自行定位。适用于自定义聊天 UI,完全控制。
工作流程
- 检查:capacitor.config.* 中的 plugins.Keyboard、@capacitor/keyboard 版本(8.0.4+ 包含 iOS 26 与 Android SystemBars 修复)、是否使用 Ionic、@capacitor/status-bar / SystemBars 配置,以及出问题页面的 CSS(position: fixed、100vh)。
- 在真机上复现(模拟器常使用硬件键盘:iOS Simulator -> I/O -> Keyboard -> Toggle Software Keyboard)。
- 根据上表选择 iOS resize 模式;在配置中设置,而非运行时设置,除非某个页面需要不同模式。
- 单独修复 Android(见下文)。
- 验证。
配置
// capacitor.config.ts
import { KeyboardResize, KeyboardStyle } from '@capacitor/keyboard';
plugins: {
Keyboard: {
resize: KeyboardResize.Body, // iOS only
style: KeyboardStyle.Default, // iOS only; JSON value is "DARK" | "LIGHT" | "DEFAULT"
// resizeOnFullScreen: omit on Capacitor 8+ (SystemBars handles insets; see Android notes)
autoBackdropColor: 'auto', // iOS, 8.0.4+: 'off' (default) | 'auto' | 'dom'
},
},
JSON 配置中字符串值:style 为大写("DARK"),resize 为小写("body")。
自定义定位(resize: none 或聊天 UI)
import { Capacitor } from '@capacitor/core';
import { Keyboard } from '@capacitor/keyboard';
if (Capacitor.isNativePlatform()) {
Keyboard.addListener('keyboardWillShow', ({ keyboardHeight }) => {
document.documentElement.style.setProperty('--kb', `${keyboardHeight}px`);
});
Keyboard.addListener('keyboardWillHide', () => {
document.documentElement.style.setProperty('--kb', '0px');
});
}
.composer {
position: fixed;
inset-inline: 0;
bottom: max(var(--kb, 0px), env(safe-area-inset-bottom));
}
使用 max(),而非 +:键盘弹起时 home 指示条内边距已被覆盖。
Android 注意事项
Android 15+(targetSdk 35)强制边到边;Android 16(targetSdk 36,Capacitor 8 默认)移除了退出选项。WebView 现在绘制在系统栏之下,因此必须处理键盘内边距。@capacitor/keyboard 7.0.2 修复了 Android 15+ 键盘上方空白,8.0.3 修复了与 SystemBars 核心插件的交互。在编写变通方案前先更新插件。
resizeOnFullScreen: true 是 Capacitor <= 7 针对全屏 / 覆盖状态栏的变通方案。在 Capacitor 8+ 上,SystemBars 核心插件处理 IME 内边距,并会记录日志:You should omit Keyboard.resizeOnFullScreen in your capacitor.config.json. Other values can lead to unexpected behavior. 除非 SystemBars.insetsHandling 为 disable。应移除该项。
不要添加 android:windowSoftInputMode="adjustPan" 来修复重叠;它会平移整个窗口并破坏固定头部。模板已省略它(默认 resize 行为)。
env(keyboard-inset-height) 和 interactive-widget viewport meta 是 Chromium 特性;在依赖它们之前,请在目标 Android System WebView 版本上测试,且绝不要在 iOS 上使用。
iOS 注意事项
计算后 font-size < 16px 的输入框会使 iOS 在聚焦时缩放。输入框应使用 font-size: 16px(或更大);不要全局禁用用户缩放(maximum-scale=1),因为这会损害可访问性。
setAccessoryBarVisible({ isVisible: false }) 在 iPhone 上隐藏上一项/下一项/完成栏;在 iPad 上无效。
setScroll({ isDisabled: true }) 阻止键盘打开时 WebView 滚动视图回弹;与 resize: none 搭配用于自定义布局。
iOS 26 键盘回归问题和 iPad Magic Keyboard 黑色 QuickType 栏已在 @capacitor/keyboard 8.0.4 中修复。如果键盘后方出现黑/白条带,设置 autoBackdropColor: 'auto'(使用配置中的 backgroundColor,否则使用 DOM body 背景)或 'dom'。
验证
- 运行 npx cap sync,并在实体 iPhone 和 Android 15+/16 设备上运行。
- 对每个表单页面:聚焦第一个和最后一个输入框;聚焦字段保持可见;页脚贴合键盘;键盘上方无间隙;键盘打开时旋转屏幕布局保持正常。
- 通过滑动/返回按钮关闭:keyboardWillHide 触发,--kb 恢复为 0。
- iOS:确认聚焦时不缩放;辅助栏状态与设计一致。
- 检查版本:npm ls @capacitor/keyboard @capacitor/core。
错误处理
- "Keyboard" plugin is not implemented on web 或 "Keyboard.setAccessoryBarVisible()" is not implemented on android:插件/方法在该平台不可用。用 Capacitor.getPlatform() === 'ios' 做保护。
- show() 在 iOS 上无效:show() 仅限 Android。改为在用户手势中聚焦输入框。
- 键盘关闭后页脚浮在中间(Android):键盘无动画隐藏时 WebView 高度未重置。更新到 @capacitor/keyboard 8.0.4+。
- Android 15+ 键盘上方白条:边到边内边距 + 旧插件。更新插件(7.0.2+ / 8.0.3+);在 Capacitor 8 上移除 resizeOnFullScreen。
- Logcat SystemBars: You should omit
Keyboard.resizeOnFullScreen...:旧配置与 SystemBars 内边距处理冲突。从配置中删除 resizeOnFullScreen。 - iOS 上基于 vh 的屏幕缩小:resize: native 改变了视口。切换到 body 或 none。
- Ionic 内容跳动两次:resize: native/body 加上 Ionic 自身处理。使用 resize: 'ionic'。
- 导航后监听器触发两次:监听器在每次页面挂载时添加,从未移除。保留返回的句柄,并在卸载时 await handle.remove()。
- iPad 配硬件键盘时黑色 QuickType 栏:8.0.4 之前的插件 bug。更新插件。
资源
- Keyboard 插件 API:https://capacitorjs.com/docs/apis/keyboard
- 插件变更日志:https://github.com/ionic-team/capacitor-keyboard/blob/main/CHANGELOG.md
- System Bars(边到边):https://capacitorjs.com/docs/apis/system-bars