前言


最近在做 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. 常用类-Excel-使用Aspose.Cells插件

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Xm ...

  2. Java开发人员必备十大工具

    Java世界中存在着很多工具,从著名的IDE(例如Eclipse,NetBeans和IntelliJ IDEA)到JVM profiling和监视工具(例如JConsole,VisualVM,Ecli ...

  3. Ling to sql 多表查询,多个条件进行关联

    使用多表查询进行关联时,提示 join子句中其中一个表达式的类型不正确,注意字段类型和名称要一致,否则join时提示语法错误,错误截图如下 var incomeDetails = from a in ...

  4. iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?

    题目: 假设我们有一个ViewController, Category A(ViewController), Category B(ViewController), Category C(ViewCo ...

  5. 中文版 Apple 官方 Swift 教程《The Swift Programming Language》

    简介 欢迎使用 Swift 关于 Swift 版本兼容性 Swift 初见 Swift 版本历史记录 Swift 教程 基础部分 基本运算符 字符串和字符 集合类型 控制流 函数 闭包 枚举 类和结构 ...

  6. 【JDBC】CRUD操作

    JDBC的CRUD操作 向数据库中保存记录 修改数据库中的记录 删除数据库中的记录 查询数据库中的记录 保存代码的实现 package demo1; import java.sql.Connectio ...

  7. iTerm2 使用代理

    0x00 事件 因为 brew 安装极慢,所以需要 iTerm2 设置代理解决速度问题. 0x01 解决 代理软件开启本地 Http 端口: iTerm 设置代理: $ vim ~/.zshrc # ...

  8. python字典中列表追加数据

    dict = {} for i in range(1, 6): if i not in dict: dict[i] = [] for j in range(101, 106): dict[i].app ...

  9. HTTPS混合内容解析

    什么是HTTPS混合内容 我们可能会有这样的经验,当我们通过HTTPS访问一个网站的时候,突然有提示:“本页面包含有不安全的内容”.这个时候会询问是否显示“不安全的内容”,这个时候,就是遇到了有混合内 ...

  10. HTML5应用 转 Android、Windows Phone 应用

    一.HTML5 转 Android 目标SDK:API 20 1.新建一个 Blank Activity 的应用 2.在 AndroidManifest.xml 文件中添加联网权限 <uses- ...