平板电脑或手机等设备通常具有用于输入文本的虚拟键盘。
与始终存在且始终保持不变的物理键盘不同,虚拟键盘会根据用户的操作显示和隐藏,并且还可以根据用户的操作进行动态调整,例如根据 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
是一个属性,其关键字是字符串 auto
和 manual
。在 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 做出了贡献。