跳到主要内容

键盘遮挡输入问题处理

产生问题原因

获知软键盘的弹起还是收起状态很重要,后面的兼容处理都要以此为前提。然而,H5 并没有直接监听软键盘的原生事件,只能通过软键盘弹起或收起,引发页面其他方面的表现间接监听。并且,在IOS 和 Android 上的表现不尽相同,定位分析深层原因,我们得知:

1.Android端

Android webview在【系统内核】下,可能会出现软键盘弹起后,遮挡了输入框和焦点的问题。这是因为软键盘弹起后,webview没有自动适应高度,从而没有通知web的onresize事件造成的。此时在页面下方的输入框没有自动上移,便被弹起的软键盘遮挡了。这种问题容易出现在类似IM聊天输入框在下方的情况,在页面顶部的输入框不会出现这种问题(因为软键盘挡不到这么高的地方)。

2.iOS端

在 IOS 上,使用第三方输入法,高度计算存在偏差,导致在有些输入法弹起,将输入框挡住一部分。或者是在IOS12 上,微信版本 v6.7.4 及以上,输入框获取焦点,键盘弹起,页面(webview)整体往上滚动,当键盘收起后,不回到原位,导致键盘原来所在位置是空白的。

总之,在 Android 和 IOS 上,获知软键盘弹起和收起状态存在差异,且页面 webview 表现不同。

解决方法

分情况处理:

Android 下解决起来比较简单,我们可以借助 Element.scrollIntoView() 这个方法来解决。

iOS下我们可以借助 document.body.scrollTop 来实现

const ua = navigator.userAgent;
const iOS = /iPad|iPhone|iPod/.test(ua);
const input = document.querySelector('#input');

input.addEventListener('focus', () => {
setTimeout(() => {
if (iOS) {
if (!/OS 11_[0-3]\D/.test(ua)) {
document.body.scrollTop = document.body.scrollHeight; // 元素的顶端将和其所在滚动区的可视区域的顶端对齐
}
} else {
input.scrollIntoView(true);
}
}, 300);
});

总结

综合上面键盘弹起和收起在 IOS 和 Android 上的不同表现,我们可以分开进行如下处理来监听软键盘的弹起和收起:在 IOS 上,监听输入框的 focus 事件来获知软键盘弹起,监听输入框的 blur 事件获知软键盘收起。 在 Android 上,监听 webview 高度会变化,高度变小获知软键盘弹起,否则软键盘收起。H5 端坑很多,需要不断尝试。了解软键盘弹起页面在 IOS 和 Android 上的表现差异是前提,同时要考虑到第三方输入法和某些浏览器上的差别。

考虑更深次的原因,比如iOS上开发时候升级更新 XCode、使用 WKWebView,android上升级X5内核(在X5内核下不存在此问题,X5内核自己做了适配)。