移動端 Web 頁 input 控制軟鍵盤

從交互層面上來說,完成一個功能(得到想要的信息)的過程稱之爲用戶路徑。用戶路徑越長,完成功能的複雜度就越高,用戶體驗也就越差。所以當打開一個須要用戶填寫信息的表單界面時,爲了提升可用性,PC 端通常會將光標聚焦到對應輸入框(input),移動端也是同理,讓對應的 input 得到 focus 狀態,喚起軟鍵盤,方便用戶直接輸入。 
本文暫且不論 PC 端的場景,在移動端(iOS、Android)實現這個看似不起眼的效果實際上是須要通過一番折騰,咱們慢慢往下看如下三種經常使用場景。
javascript

1、當進入表單頁時,讓軟鍵盤自動打開前端

這個需求比較常見,可是也是最棘手的。講科學的話,咱們能夠直接在 JS 裏獲取 input ,給它 focus 下就搞定了。可是這在移動端瀏覽器裏是行不通的。。 
另外,H5 提供了 autofocus 屬性,這個屬性的兼容性在 caniuse 上顯示並不支持 iOS Safari,Android 也是要到 4.4 纔開始支持,所以咱們能夠忽略這個屬性,不過下文會再次提到這個屬性。 
所以在 iOS 裏想要在頁面 load 完成後自動聚焦 input,打開鍵盤目前來說不是很現實。 
最難過的是 Android 也不行,目前進行了簡單的測試系統瀏覽器和 App 內嵌 WebView,H5 中的 input 是聚焦狀態,可是沒法喚起鍵盤,鍵盤,鍵盤。。。 
場景一,暫時無解……(下文提到在 Hybrid App 中能夠實現)
java

2、當點擊頁面中某個元素喚起軟鍵盤web

這個相對於場景一,多了用戶交互這一步。那麼這樣是否是就可使用 JS 在 iOS 上成功的喚起鍵盤了呢?答案是確定的。瀏覽器

<!-- HTML -->安全

<input id="input" type="text" placeholder="this a input"/>函數

<button id="J-focus-btn" onclick="clickFocusBtn()">focus input</button>測試

// JS優化

function clickFocusBtn() {ui

    document.getElementById("input").focus();

}

若是有使用 zepto 的童鞋,這邊須要注意下爲了 iOS,你不能使用 tap 事件。

// JS  zepto

 

$('#J-focus-btn').on('tap', function() {

   $('#input').focus();

});

如上使用了 zepto tap 事件,它在 iOS 上並不能達到預期效果,這裏面就涉及到了 iOS WebView 的一種默認安全機制。在 UIWebView 中有一個屬性:

@property (nonatomic) BOOL keyboardDisplayRequiresUserAction NS_AVAILABLE_IOS(6_0); // default is YES

這個屬性默認是 YES,也就是說鍵盤的出現必需要用戶交互。那咱們就知道緣由了,zepto 內部觸發 tap 事件是在 setTimeout 內,也就是說執行 focus 時,執行環境並非用戶觸發的,所以 focus 被攔截掉了。

// zepto

 

tapTimeout = setTimeout(function() {

  // trigger event

}, 0)

若是咱們是寫 Hybird App 的頁面,則可讓 Native Coder 將 UIWebView 的 keyboardDisplayRequiresUserAction 屬性設置爲 NO,則沒必要操心這個問題了。 
不過 iOS 的 WKWebView 不支持這個屬性了,可是在 StackOverflow 上有方案,可使用 runtime 的 method swizzling hack 掉,詳見此連接 stackoverflow.com/questions/3… 
那麼場景一在本身的 Hybrid App 裏仍是能夠實現的,固然系統原生的 Safari 瀏覽器咱們無能爲力,能優化一點是一點吧。 
同時測試了下 autofocus 屬性,在 keyboardDisplayRequiresUserAction 設置爲 NO 的狀況下,它也是能正常工做的。 
在 Android 底下,也是能夠實現用戶點擊以後 focus 指定 input 的效果,並且沒有 iOS 的那個機制。

3、表單頁多個 input 依次自動聚焦

這個場景實際上是場景1、二的結合,綜合上面兩個場景的測試分析,在本身的 * iOS Hybrid App * 裏依賴 Native 的 WebView 是能夠實現的,在 Android 和外部瀏覽器中能夠實現除第一次聚焦外的自動聚焦。。 
目前 iOS UIWebView 設置 keyboardDisplayRequiresUserAction = NO 的狀態下,須要在 blur 事件內延遲 focus 才能生效(具體緣由暫時不明):

// Hybrid App 內

 

document.querySelector('#input1').focus();

document.querySelector('#input1').addEventListener('blur', function() {

   setTimeout(function() {    // 必須延遲

       document.querySelector('#input2').focus();

   }, 200);

});

在系統 Safari 內,則由於 keyboardDisplayRequiresUserAction 默認爲 YES,所以不容許在用戶交互產生的執行環境以外調用 focus,所以不能延遲執行。

// 系統 Safari 內

 

document.querySelector('#input1').focus();

document.querySelector('#input1').addEventListener('blur', function() {

   document.querySelector('#input2').focus();

});

而在安卓中,頁面加載完後自動聚焦仍舊只是出現光標,不彈出鍵盤。。。後續自動聚焦則沒問題,以下圖所示狀態。。。 
 
爲了解決這個問題,在 Hybrid App 中能夠經過 JSBridge 讓 Android 原生進行喚起,後續 blur 事件中再 focus 則不須要原生再進行處理。

// Android 喚起鍵盤

 

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

imm.showSoftInput(view, 0);   // view 爲當前 webview

小結

總結下:

  • 要實現頁面加載完成後自動聚焦到 input 並彈出鍵盤,依賴 iOS App 的 WebView 將 keyboardDisplayRequiresUserAction 設置爲 NO,就能夠支持。Android 底下只能依賴 JSBridge 調用 Android 原生方法喚起鍵盤 。

  • 點擊元素聚焦指定 input,iOS / Android 都支持,可是 iOS 中必須保證 focus 是在用戶操做事件的函數執行環境中直接調用(Zepto tap 的坑)。

  • 依次聚焦 input,iOS 中有點特殊,具體仍是看上文場景三。。。

      LINKS

    • https://stackoverflow.com/questions/6287478/mobile-safari-autofocus-text-field

    • https://stackoverflow.com/questions/32407185/wkwebview-cant-open-keyboard-for-input-field    

    • 推薦↓↓↓ 

       

       

      web前端開發熱門新聞,每日 10:24 播報

相關文章
相關標籤/搜索