SuperAPI AI 工具集

capacitor-keyboard

编程与开发

查看项目

更新于 10-15 14:36

技能介绍

用途

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,完全控制。

工作流程

  1. 检查:capacitor.config.* 中的 plugins.Keyboard、@capacitor/keyboard 版本(8.0.4+ 包含 iOS 26 与 Android SystemBars 修复)、是否使用 Ionic、@capacitor/status-bar / SystemBars 配置,以及出问题页面的 CSS(position: fixed、100vh)。
  2. 在真机上复现(模拟器常使用硬件键盘:iOS Simulator -> I/O -> Keyboard -> Toggle Software Keyboard)。
  3. 根据上表选择 iOS resize 模式;在配置中设置,而非运行时设置,除非某个页面需要不同模式。
  4. 单独修复 Android(见下文)。
  5. 验证。

配置

// 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