使用 VirtualKeyboard API 进行完全控制

浏览器支持

  • Chrome:94.
  • Edge:94.
  • Firefox:不受支持。
  • Safari:不受支持。

来源

平板电脑或手机等设备通常具有用于输入文本的虚拟键盘。 与始终存在且始终保持不变的物理键盘不同,虚拟键盘会根据用户的操作显示和隐藏,并且还可以根据用户的操作进行动态调整,例如根据 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 属性类似,即对应于 top、right、bottom 和/或 left 属性。

  • 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 指定,并由同样来自 Microsoft 的前编辑 Grisha Lyukshin 做出了贡献。