移动端 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 播报

相关文章
相关标签/搜索