前言


最近在做 webapp,遇到了很多移动端兼容的问题,其中一个问题就是:输入框触发 focus 后,键盘弹出,然后遮住了输入框。

然后在AndroidIOS上,这个问题的表现形式不一样,而原生键盘和第三方键盘也不一样,但引起的问题都是一样的:输入框被遮住了。

需要的效果


在键盘弹出时,获得焦点的输入框要在可视区域内,效果如下图:

键盘弹出、收起的表现


  1. IOS:

    输入框获取焦点,键盘弹出,webview高度不会改变,但webview会往上滚,且最大滚动高度scrollTop为键盘高度。

    点击键盘上的收起按钮,或者输入框以外的页面区域时,输入框失去焦点,键盘收起。

  2. Android:

    输入框获取焦点,键盘弹出,但是webview高度会发生改变,高度为原高度减去软键盘高度。

    点击输入框以外的区域时,输入框失去焦点,软键盘收起。而点击键盘上的收起按钮时,键盘收起 ,但输入框并不会失去焦点,

解决方案


当输入框被挡住,在IOS中,webview会往上滚一段距离,使得获取焦点的输入框自动处于可视区,而在Android里,只会改变webview高度,而不会发生焦点元素滚动到可视区的事情。

所以IOS可以不用管,而Android需要在键盘弹出的时候,将输入框滚动到可视区。

获取设备类型


首先是要获取设备类型,通过navigator.userAgent获取即可。

const judgeDeviceType = (() => {
let deviceType = null; return () => {
if (!deviceType) {
const ua = window.navigator.userAgent.toLocaleLowerCase();
const isIOS = /iphone|ipad|ipod/.test(ua);
const isAndroid = /android/.test(ua);
const isMiuiBrowser = /miuibrowser/.test(ua); deviceType = {
isIOS: isIOS,
isAndroid: isAndroid,
isMiuiBrowser: isMiuiBrowser
};
} return deviceType;
};
})();

监听事件


IOS 可以通过focusblur事件监听键盘弹出、收起,但 Android 不行,但因为webview高度会变,所以通过监听resize事件解决。

export function listenAndroidKeybord() {
const { isAndroid } = judgeDeviceType(); if (isAndroid) {
const androidResize = function() {
// 将当前焦点元素滚动到可视区
activeElementScrollIntoView();
}; // android 键盘弹出、收起,可视区高度会发生变化
window.addEventListener('resize', androidResize, false); return () => {
window.removeEventListener('resize', androidResize, false);
};
}
}

将元素滚动到可视区


要将元素滚动到可视区,主要有两个方法:scrollIntoViewscrollIntoViewIfNeeded,兼容性在移动端都很不错。

function activeElementScrollIntoView() {
const activeEl = document.activeElement; if (
activeEl.tagName === 'INPUT' ||
activeEl.tagName === 'TEXTAREA'
) {
window.setTimeout(() => {
if ('scrollIntoView' in activeEl) {
activeElt.scrollIntoView();
} else {
activeEl.scrollIntoViewIfNeeded();
}
}, 100);
}
}

MiuiBrowser


以上代码可以说解决了大部分浏览器键盘遮挡问题了,但我用自己的小米手机自带的小米浏览器测试时,出了问题,键盘弹出,页面纹丝不动,手动去拖,有时行,有时不行。

搞了很久,发现了两个问题,我这手机上自带的小米浏览器,userAgent 上没有带Android标识,但有MiuiBrowser标识,。然后,页面有时能拖动,有时不能拖动,我猜应该是webview的可视区高度变化有问题,或者是我的代码监听resize导致有问题。

解决方案

  1. 增加设备类型判断

    const ua = window.navigator.userAgent.toLocaleLowerCase();
    const isMiuiBrowser = /miuibrowser/.test(ua);
  2. 通过监听focusblur事件来监听键盘弹出、收起,然后给body加高度

    body, html {
    height: 100%;
    }
    function listenMiuiBrowserKeybord() {
    const { isMiuiBrowser } = judgeDeviceType(); if (isMiuiBrowser) {
    const inputFocus = function() {
    document.body.style.marginBottom = '50px';
    activeElementScrollIntoView();
    }; const inputBlur = function() {
    document.body.style.marginBottom = '0px';
    activeElementScrollIntoView();
    }; let $inputs = document.getElementsByTagName('input');
    for (let i = 0; i < $inputs.length; i++) {
    $inputs[i].addEventListener('focus', inputFocus, false);
    $inputs[i].addEventListener('blur', inputBlur, false);
    } return () => {
    for (let i = 0; i < $inputs.length; i++) {
    $inputs[i].removeEventListener('focus', inputFocus, false);
    $inputs[i].removeEventListener('blur', inputBlur, false);
    }
    };
    }
    }

坑点:这种方案虽然解决了弹出问题,但点击键盘收起按钮,Android 下输入框并不会失去焦点,需要失去焦点才能让 body 增加的高度变为 0。

备注


解决方案并不完善,踩坑路漫漫。

H5 移动端 键盘遮挡焦点元素解决方案的更多相关文章

  1. iOS 键盘遮挡输入框万能解决方案(多个输入框)

    效果图如下: 思路分析: 代码: 知识点: 问题: 效果图如下: 思路分析: 当我们有很多输入框时,有时候键盘弹出来会遮挡着输入框.我们需要获取输入框和键盘相对于最外层视图的位置来判断是否遮挡,如果遮 ...

  2. h5移动端常见的问题及解决方案

    01.ios端兼容input高度 #问题描述 input输入框光标,光标的高度和父盒子的高度一样,而android手机没问题 android ios #产生原因 通常我们习惯用height属性设置行间 ...

  3. 移动端键盘遮挡input问题

    在开发移动端项目的时候测试提出优化问题,即: input 获取焦点弹出系统虚拟键盘时, input 被键盘遮挡问题(PS:此问题只在安卓手机上有,ios系统是有自动处理的). 解决办法为: 当 inp ...

  4. 常见的H5移动端Web页面Bug问题解决方案总汇

    解决jquery ajax调用远程接口的跨域问题 首先,接口必须允许远程调用.这是后端或者运维的事情.你必须保证你得到的一个接口是允许远程调用的.否则,就没啥了. $.ajax({ type:'get ...

  5. h5开发安卓软键盘遮挡解决方案

    //处理input focus时被键盘遮挡问题 inputFocus:function(){ if(/Android [4-6]/.test(navigator.appVersion)) { wind ...

  6. 移动端页面input输入框被键盘遮挡问题

    <body class="layout-fixed"> <!-- fixed定位的头部 --> <header> </header> ...

  7. Android软键盘遮挡的四种解决方案

    问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时输入 ...

  8. iOS学习——键盘弹出遮挡输入框问题解决方案

    在iOS或Android等移动端开发过程中,经常遇到很多需要我们输入信息的情况,例如登录时要输入账号密码.查询时要输入查询信息.注册或申请时需要填写一些信息等都是通过我们键盘来进行输入的,在iOS开发 ...

  9. js-移动端android浏览器中input框被软键盘遮住的问题解决方案

    我遇到的问题:在一个页面里有一个弹出层之前我给我的最外层加了固定定位 用了下面的方法也不好使:没有办法我将之改为绝对定位层级变高在加上一个顶部标签通过js计算顶部高度来实现满屏遮挡: <sect ...

随机推荐

  1. pecl安装和卸载示例

    比如安装MongoDB扩展 命令行下输入: [#] /usr/local/php/bin/pecl install mongodb ......嗒吧嗒吧一大堆输出后 Build process com ...

  2. css网页布局模板

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. echarts背景颜色渐变的三种类型

    // 线性渐变,多用于折线柱形图,前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1,相当于在图形包围盒中的百分比,如果 globalCoord 为 `true`,则该四个值是绝对的 ...

  4. 推荐一个Emoji框架

    表情的需求很常见.有的可以看看,没有的可以先收藏以备不时之需. 这个框架的反应速度很快,界面简洁漂亮,功能完备. 而且代码简洁易懂,便于学习. GitHub:https://github.com/ne ...

  5. linux学习(八)Shell中变量的数学运算

    目录 常见的运算符 expr命令 @(Shell中变量的数学运算) 常见的运算符 环境变量 说明 + 加 - 减 * 乘 / 除 % 取模 因为Shell中将*作为通配符使用, expr命令 expr ...

  6. ORA-39901 EXPDP分区报错/分区表删除不完全

    [oracle@localhost zgy]$ expdp orders/orders directory=DUMPDIR DUMPFILE=test_exp.dmp TRANSPORT_TABLES ...

  7. PHP删除数组中重复的元素

    array_unique($arr): //删除重复元素 $arr = [1,2,3,0,1]; echo '<pre>'; var_dump($arr); $arr = array_un ...

  8. coalesce搭配nullif使用

    with t1 as ( select NUll as col1, '' as col2, 'aaa' as col3 ) --关于COALESCE用法 当col1 为 Null时候返回 col2 依 ...

  9. 使用VS Code开发纸壳CMS自动编译主题压缩CSS,JS

    Visual Studio Code (简称 VS Code / VSC) 是一款免费开源的现代化轻量级代码编辑器,支持语法高亮.智能代码补全.自定义热键.括号匹配.代码片段.代码对比 Diff.GI ...

  10. Java 的synchronized关键字使用

    synchronized 关键字是实现锁的一种方式,是在jvm层面实现的非公平锁,以下是使用synchronized的四种方式 synchronized 特性: 1.非公平锁 2.可重入性 1.作用在 ...