javascript 在iOS8中使用.focus()會在觸摸後顯示虛擬鍵盤和滾動頁面




uikeyboard autofocus (6)

我有一個解決方案:

  1. 禁用所有輸入
  2. 啟用您想要關注的輸入
  3. 將焦點設置為該輸入
  4. 重新啟用所有其他輸入

在iOS8之前,在輸入元素上使用Javascript .focus()方法似乎沒有效果(虛擬鍵盤不會顯示)。 在最新的iOS 8版本之後,運行.focus()方法似乎對頁面加載沒有影響,但是一旦用戶觸摸屏幕上的任何地方,虛擬鍵盤將立即出現並將頁面滾動到焦點對準的元素。 (當我使用HTML屬性“autofocus”時,這也是一個問題)

此更改導致我的網站上的iOS8用戶出現問題。 當用戶嘗試單擊頁面上的按鈕時,突然滾動和鍵盤外觀會導致他們無意中單擊屏幕下方的按鈕。

我假設這是iOS8中的一個錯誤而不是故意的功能,我的問題是解決這個問題最有效的解決方案是什麼?

每次使用.focus()方法時,是否必須檢查navigator.userAgent以查看設備是否為iOS8?


似乎在iOS 8中對javascript focus()命令的默認處理進行了API更改。 如果您的應用程序是一個混合應用程序,您可以直接控制Apple的Web視圖外觀,則以下內容直接來自apple docs。

一個布爾值,指示Web內容是否可以以編程方式顯示鍵盤。

[myWebView setKeyboardDisplayRequiresUserAction:YES];

當此屬性設置為YES時,用戶必須顯式點擊Web視圖中的元素以顯示該元素的鍵盤(或其他相關輸入視圖) 。 設置為NO時,元素上的焦點事件會導致輸入視圖自動顯示並與該元素關聯。

此屬性的默認值為YES。

從最後一段看來,這種方法調用似乎並不嚴格用於鍵盤。 它表示它適用於全面的輸入視圖,即下拉和日期選擇器等。

似乎有一個錯誤,因為此方法調用目前不適合我。 我收到的當前行為對應,就好像它默認為NO。


我已將有關此問題的錯誤記錄到Apple Bug Reporter中,並將其關閉為重複,這表明他們正在努力修復此問題。 不幸的是,他們沒有給我更多關於重複項目或問題本身的信息。 我只能看到重複項狀態,即Open。


看起來你肯定遇到了iOS 8的bug。 在iOS7中,Safari會(顯然)忽略或保持在頁面加載之前設置焦點的未聚焦元素。 這包括<input autofocus>input.focus() ,它們發生在某個點上,可能是頁面加載(我只使用內聯腳本測試)。

在iOS 8中,Safari現在顯然已經記住了該元素是專注的,但實際上並沒有將其聚焦到觸地事件之前。 然後盲目地向接收到觸摸的任何元素發送點擊事件。

對於在頁面加載後發生的input.focus()兩個瀏覽器的行為相同。 它們都縮放到元素並調出鍵盤。

測試:

好消息是,您只需要擔心要預先聚焦的元素的新行為。 另一個好消息是,雖然您必須使用用戶代理解決方法,但您可以將它用於所有iOS版本,因為它們的行為就像您沒有自動對焦:

if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
    element.focus();
}

這似乎是http://www.google.com基於一些基本用戶代理測試的方法:

  • Mac Book Pro:頁面加載前自動對焦。
  • iPhone:沒有自動對焦功能
  • iPad:沒有自動對焦功能
  • Kit Kat(Android): 頁面加載關注,可能會對軟件鍵盤的存在進行額外檢測。

如果還沒有,你應該繼續通過https://bugreport.apple.com向Apple提交雷達。


如果您正在開發Cordova項目,則可以通過添加此行來修復它

<preference name="KeyboardDisplayRequiresUserAction" value="false" />

到您的config.xml文件。 在IOS 8.3和IOS 8.4中測試過


這是jQuery.focus的條件monkeypatch,因此您無需在任何地方添加userAgent測試。

JavaScript的

if (/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
  (function($) {
    return $.fn.focus = function() {
      return arguments[0];
    };
  })(jQuery);
}

CoffeeScript的

if /iPad|iPhone|iPod/g.test navigator.userAgent
  (($) ->
    $.fn.focus = ->
      arguments[0]
  )(jQuery)

注意:我正在返回arguments[0]因此我們不會破壞方法鏈,例如$(el).focus().doSomethingElse()







autofocus