H5 鍵盤兼容性小結

H5 鍵盤兼容性小結

在 H5 項目中,咱們會常常遇到頁面中存在單個甚至多個 input/textarea 輸入框與底部固定元素的佈局狀況。在 input/textarea 輸入框獲取焦點時,會自動觸發鍵盤彈起,而鍵盤彈出在 ios 與 android 的 webview 中表現並不是一致,同時當咱們主動觸發鍵盤收起時也一樣存在差別化。而不管如何,咱們但願功能流暢的同時,儘可能保持用戶體驗的一致性,所以有了下面一系列兼容性問題的研究。android

 

1. 鍵盤彈出的不一樣表現

  • IOS:IOS 的鍵盤處在窗口的最上層,當鍵盤彈起時,webview 的高度 height 並無改變,只是 scrollTop 發生變化,頁面能夠滾動。且頁面能夠滾動的最大限度爲彈出的鍵盤的高度,而只有鍵盤彈出時頁面剛好也滾動到最底部時,scrollTop 的變化值爲鍵盤的高度,其餘狀況下則沒法獲取。這就致使在 IOS 狀況下難以獲取鍵盤的真實高度。
  • Android: webview 中留出空間,該空間小於等於的鍵盤空間,變化的高度差會隨着佈局而不一樣,有的認爲 鍵盤高度 + 頁面高度 = 原頁面高度; 是錯誤的誤導,只有在某種很巧合的佈局狀況下才可套用此公式。

2. 鍵盤收起的不一樣表現

  • IOS:觸發鍵盤上的按鈕收起鍵盤或者輸入框之外的頁面區域時,輸入框會失去焦點,所以會觸發輸入框的 blur 事件。
  • Android: 觸發鍵盤上的按鈕收起鍵盤時,輸入框並不會失去焦點,所以不會觸發頁面的 blur 事件;觸發輸入框之外的區域時,輸入框會失去焦點,觸發輸入框的 blur 事件。

3. 監聽鍵盤的彈出與收起

在 h5 中目前沒有接口能夠直接監聽鍵盤事件,但咱們能夠經過分析鍵盤彈出、收起的觸發過程及表現形式,來判斷鍵盤是彈出仍是收起的狀態。ios

  • 鍵盤彈出:輸入框獲取焦點時會自動觸發鍵盤的彈起動做,所以,咱們能夠監聽輸入框的 focus 事件,在裏面實現鍵盤彈出後所需的頁面邏輯。這在 ios 及 android 中表現一致。
  • 鍵盤收起:從第 2 部分可知,觸發鍵盤收起的不一樣形式會存在差別化表現,當觸發其餘頁面區域收起鍵盤時,咱們能夠監聽輸入框的 blur 事件,在裏面實現鍵盤收起後所需的頁面邏輯。而在經過鍵盤按鈕收起鍵盤時在 ios 與 android 端存在差別化表現,下面具體分析:
    • IOS:觸發了輸入框 blur 事件,仍然經過該辦法監聽。
    • Android:沒有觸發輸入框的 blur 事件。但經過第 一、2 部分咱們能夠知道,在 android 中,鍵盤的狀態切換(彈出、收起)不只和輸入框關聯,同時還會影響到 webview 高度的變化,那咱們不妨經過監聽 webview height 的變化來判斷鍵盤是否收起。

下面舉例說明,其中頁面中含有一個輸入框:web

<div class="txd"> Welcome to TXD! </div> <div class="input"> <input id="input" type="tel" /> </div> 複製代碼

ios & android 鍵盤彈出:瀏覽器

const $input = document.getElementById('input'); $input.addEventListener('focus', () => { // 處理鍵盤彈出後所需的頁面邏輯 }, false); 複製代碼

ios 鍵盤收起:bash

const $input = document.getElementById('input'); $input.addEventListener('blur', () => { // 處理鍵盤收起後所需的頁面邏輯 }, false); 複製代碼

android 鍵盤彈出與收起:iphone

/*鍵盤彈起後頁面高度變小*/
const originHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.addEventListener('resize', () => { const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight; if (resizeHeight < originHeight) { // 鍵盤彈起所後所需的頁面邏輯 } else { // 鍵盤彈起所後所需的頁面邏輯 } }, false); 複製代碼

在實踐中經過判斷 userAgent 來決定使用哪一種方法:佈局

const ua = window.navigator.userAgent.toLocaleLowerCase();
const isIOS = /iphone|ipad|ipod/.test(ua);
const isAndroid = /android/.test(ua);
複製代碼

4. 使用案例

接下來根據上面的討論說明幾種常見場景:post

(1)頭部及中間輸入框處於正常的文檔流,底部元素 fixed優化

 

ios 鍵盤遮擋在頁面上,頁面高度始終不變,頁面能夠滾動,底部元素被遮擋;ui

android 頁面高度減小,頁面不可滾動,fixed 元素的 bottom 屬性的基線爲鍵盤;

(2)頭部及輸入框處於正常文檔流,且所佔可視區域變大,底部元素 fixed

 

ios 的 height 沒有發生變化,頁面能夠滾動;

android 頁面高度變小,但爲了使正常文檔流的元素能夠正常顯示,頁面能夠上下滾動,fixed 元素的 bottom 屬性的基線爲鍵盤;

(3)頭部處於正常文檔流,輸入框脫離正常文檔流 fixed bottom 定位


(上面爲了便於觀察,將輸入框包裹元素的背景設置了透明度)

 

ios 的 height 沒有發生變化,且始終保證輸入框處於可視區域中;

android 頁面高度變小,頁面不可滾動,fixed 輸入框 bottom 屬性的基線爲鍵盤;

5. 小結

  1. 在 ios 中,不管何種佈局,爲了使輸入框展現在可視區域中,鍵盤彈出時,頁面會向上滾動,該過程與 Element.scrollIntoViewIfNeeded() 方法(將不在瀏覽器窗口的可見區域內的元素滾動到瀏覽器窗口的可見區域)產生的效果一致;且高度始終不變,頁面可滾動。
  2. 在 android 中,鍵盤喚起後,頁面可滾動與否由其處在正常文檔流中的元素決定:若是正常文檔流中的元素可全量展現,頁面不可滾動,不然頁面支持滾動;
  3. 在 android 中,鍵盤喚起後,fixed 元素的基準會發生變化:根據 bottom 定位的元素,其基線變爲鍵盤上部;根據 top 定位的元素,仍然根據頁面頂部,所以爲照顧正常文檔流及 fixed 元素的用戶體驗,有的元素可根據頂部定位,有的能夠根據底部定位。

在瞭解清楚 h5 中鍵盤的彈出收起的性質後,在處理兼容性問題會容易不少。同時也可以使用Element.scrollIntoViewIfNeeded() 方法輔助解決問題(好比在切換不一樣的輸入法時,可能致使有用信息被遮擋的狀況)優化體驗。

做者:阿里巴巴TXD連接:https://juejin.im/post/5c6d1c8b6fb9a049de6df441來源:掘金著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索