使用 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 屬性,也就是對應於上、右、下和/或左屬性。

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

虛擬鍵盤插邊是六個環境變數,可透過從可視區域邊緣的頂端、右側、底部和左側插邊定義矩形。寬度和高度內嵌會根據開發人員的操作需求,從其他內嵌計算而得。如果未提供備用值,每個鍵盤內嵌的預設值為 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 提供。