使用 VirtualKeyboard API 进行完全控制

浏览器支持

  • 94
  • 94
  • x
  • x

平板电脑或手机等设备通常配备用于输入文字的虚拟键盘。 与始终存在且始终相同的实体键盘不同,虚拟键盘会根据用户的操作而显示和消失,它还可以动态适应,例如根据 inputmode 属性。

这种灵活性的代价是:浏览器布局引擎必须获知虚拟键盘的存在,并且可能需要调整文档的布局以进行补偿。例如,用户即将在其中输入内容的输入字段可能会被虚拟键盘遮挡,因此浏览器必须将其滚动到视野范围内。

传统上,浏览器会自行应对这一挑战,但更复杂的应用可能需要对浏览器行为进行更多控制。例如,跨屏移动设备如果只在一个屏幕片段上显示虚拟键盘,但可用的视口在两个屏幕上都会缩小,传统方法会导致“浪费”屏幕空间。下图显示了如何使用 VirtualKeyboard API 动态优化文档的布局,以补偿虚拟键盘的存在。

传统方法会导致

在这种情况下,VirtualKeyboard API 可以派上用场。它包含三个部分:

  • navigator 对象的 VirtualKeyboard 接口,用于通过 JavaScript 以编程方式访问虚拟键盘。
  • 一组 CSS 环境变量,用于提供有关虚拟键盘外观的信息。
  • 一项虚拟键盘政策,用于确定是否应显示虚拟键盘。

当前状态

适用于桌面设备和移动设备的 Chromium 94 及更高版本均提供 VirtualKeyboard API。

功能检测和浏览器支持

如需检测当前浏览器是否支持 VirtualKeyboard API,请使用以下代码段:

if ('virtualKeyboard' in navigator) {
  // The VirtualKeyboard API is supported!
}

使用 VirtualKeyboard API

VirtualKeyboard API 向 navigator 对象添加了一个新接口 VirtualKeyboard

选择启用新的虚拟键盘行为

如需告知浏览器您要自行处理虚拟键盘遮挡问题,您需要先将布尔属性 overlaysContent 设为 true,以选择启用新的虚拟键盘行为。

navigator.virtualKeyboard.overlaysContent = true;

显示和隐藏虚拟键盘

您可以通过调用虚拟键盘的 show() 方法来以编程方式显示该键盘。为此,聚焦的元素必须是表单控件(例如 textarea 元素)或编辑宿主(例如,通过使用 contenteditable 属性)。该方法始终返回 undefined,但如果之前未显示虚拟键盘,则会触发 geometrychange 事件。

navigator.virtualKeyboard.show();

如需隐藏虚拟键盘,请调用 hide() 方法。该方法始终返回 undefined,但如果之前显示了虚拟键盘,则会触发 geometrychange 事件。

navigator.virtualKeyboard.hide();

获取当前几何图形

您可以通过查看 boundingRect 属性来获取虚拟键盘的当前几何图形。它会以 DOMRect 对象的形式公开虚拟键盘的当前尺寸。边衬区对应顶部、右侧、底部和/或左侧属性。

const { x, y, width, height } = navigator.virtualKeyboard.boundingRect;
console.log('Virtual keyboard geometry:', x, y, width, height);

了解几何图形变化

每当虚拟键盘出现或消失时,系统都会分派 geometrychange 事件。该事件的 target 属性包含 virtualKeyboard 对象,该对象包含作为 DOMRect 的虚拟键盘边衬区的新几何图形(如上文所述)。

navigator.virtualKeyboard.addEventListener('geometrychange', (event) => {
  const { x, y, width, height } = event.target.boundingRect;
  console.log('Virtual keyboard geometry changed:', x, y, width, height);
});

CSS 环境变量

VirtualKeyboard API 提供了一组 CSS 环境变量,这些变量提供有关虚拟键盘外观的信息。 它们的建模方式类似于 inset CSS 属性,即对应于顶部、右侧、底部和/或左侧属性。

  • keyboard-inset-top
  • keyboard-inset-right
  • keyboard-inset-bottom
  • keyboard-inset-left
  • keyboard-inset-width
  • keyboard-inset-height

虚拟键盘边衬区是 6 个环境变量,它们通过相对于视口边缘的顶部、右侧、底部和左侧边衬区来定义矩形。宽度和高度边衬区根据开发者工效学设计的其他边衬区计算得出。如果未提供回退值,则每个键盘边衬区的默认值为 0px

您通常可以使用如下示例中的环境变量:

.some-class {
  /**
   * Use a margin that corresponds to the virtual keyboard's height
   * if the virtual keyboard is shown, else use the fallback value of `50px`.
   */
  margin-block-end: env(keyboard-inset-height, 50px);
}

.some-other-class {
  /**
   * Use a margin that corresponds to the virtual keyboard's height
   * if the virtual keyboard is shown, else use the default fallback value of `0px`.
   */
  margin-block-end: env(keyboard-inset-height);
}

虚拟键盘政策

有时,当聚焦于可编辑元素时,不应显示虚拟键盘。例如电子表格应用,用户可以通过点按一个单元格将其值添加到另一个单元格的公式中。virtualkeyboardpolicy 是一个属性,其关键字为字符串 automanual。如果在 contenteditable 宿主元素上指定,auto 会使相应的可修改元素在获得焦点或点按该元素时自动显示虚拟键盘,而 manual 会将焦点和点按该可修改元素与虚拟键盘当前状态的变化分离。

<!-- Do nothing on regular focus, but show the virtual keyboard on double-click. -->
<div
  contenteditable
  virtualkeyboardpolicy="manual"
  inputmode="text"
  ondblclick="navigator.virtualKeyboard.show();"
>
  Double-click to edit.
</div>

演示

您可以在 Glitch 上的演示中查看 VirtualKeyboard API 的实际应用。请务必浏览源代码,了解其实现方式。虽然可以在 iframe 嵌入中观察到 geometrychange 事件,但实际的虚拟键盘行为需要在自己的浏览器标签页中打开演示。

致谢

VirtualKeyboard API 由 Microsoft 的 Anupam Snigdha 指定,前编辑 Grisha Lyukshin 也由 Microsoft 做出贡献。主打图片由 @freestocksUnsplash 上提供。