H5 键盘兼容性小结

在 H5 项目中,我们会经常遇到页面中存在单个甚至多个 input/textarea 输入框与底部固定元素的布局情况。在 input/textarea 输入框获取焦点时,会自动触发键盘弹起,而键盘弹出在 ios 与 android 的 webview 中表现并非一致,同时当我们主动触发键盘收起时也同样存在差异化。而无论如何,我们希望功能流畅的同时,尽量保持用户体验的一致性,因此有了下面一系列兼容性问题的研究。

1. 键盘弹出的不同表现

  • IOS:IOS 的键盘处在窗口的最上层,当键盘弹起时,webview 的高度 height 并没有改变,只是 scrollTop 发生变化,页面可以滚动。且页面可以滚动的最大限度为弹出的键盘的高度,而只有键盘弹出时页面恰好也滚动到最底部时,scrollTop 的变化值为键盘的高度,其他情况下则无法获取。这就导致在 IOS 情况下难以获取键盘的真实高度。
  • Android: webview 中留出空间,该空间小于等于的键盘空间,变化的高度差会随着布局而不同,有的认为 键盘高度 + 页面高度 = 原页面高度; 是错误的误导,只有在某种很巧合的布局情况下才可套用此公式。

2. 键盘收起的不同表现

  • IOS:触发键盘上的按钮收起键盘或者输入框以外的页面区域时,输入框会失去焦点,因此会触发输入框的 blur 事件。
  • Android: 触发键盘上的按钮收起键盘时,输入框并不会失去焦点,因此不会触发页面的 blur 事件;触发输入框以外的区域时,输入框会失去焦点,触发输入框的 blur 事件。

3. 监听键盘的弹出与收起

在 h5 中目前没有接口可以直接监听键盘事件,但我们可以通过分析键盘弹出、收起的触发过程及表现形式,来判断键盘是弹出还是收起的状态。

  • 键盘弹出:输入框获取焦点时会自动触发键盘的弹起动作,因此,我们可以监听输入框的 focus 事件,在里面实现键盘弹出后所需的页面逻辑。这在 ios 及 android 中表现一致。
  • 键盘收起:从第 2 部分可知,触发键盘收起的不同形式会存在差异化表现,当触发其他页面区域收起键盘时,我们可以监听输入框的 blur 事件,在里面实现键盘收起后所需的页面逻辑。而在通过键盘按钮收起键盘时在 ios 与 android 端存在差异化表现,下面具体分析:
    • IOS:触发了输入框 blur 事件,仍然通过该办法监听。
    • Android:没有触发输入框的 blur 事件。但通过第 1、2 部分我们可以知道,在 android 中,键盘的状态切换(弹出、收起)不仅和输入框关联,同时还会影响到 webview 高度的变化,那我们不妨通过监听 webview height 的变化来判断键盘是否收起。

下面举例说明,其中页面中含有一个输入框:

<div class="txd">
Welcome to TXD!
</div>
<div class="input">
<input id="input" type="tel" />
</div>
复制代码

ios & android 键盘弹出:

const $input = document.getElementById('input');
$input.addEventListener('focus', () => {
// 处理键盘弹出后所需的页面逻辑
}, false);
复制代码

ios 键盘收起:

const $input = document.getElementById('input');
$input.addEventListener('blur', () => {
// 处理键盘收起后所需的页面逻辑
}, false);
复制代码

android 键盘弹出与收起:

/*键盘弹起后页面高度变小*/
const originHeight = document.documentElement.clientHeight || document.body.clientHeight;
window.addEventListener('resize', () => {
const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
if (resizeHeight < originHeight) {
// 键盘弹起所后所需的页面逻辑
} else {
// 键盘弹起所后所需的页面逻辑
}
}, false);
复制代码

在实践中通过判断 userAgent 来决定使用哪种方法:

const ua = window.navigator.userAgent.toLocaleLowerCase();
const isIOS = /iphone|ipad|ipod/.test(ua);
const isAndroid = /android/.test(ua);
复制代码

4. 使用案例

接下来根据上面的讨论说明几种常见场景:

(1)头部及中间输入框处于正常的文档流,底部元素 fixed

ios 键盘遮挡在页面上,页面高度始终不变,页面可以滚动,底部元素被遮挡;

android 页面高度减少,页面不可滚动,fixed 元素的 bottom 属性的基线为键盘;

(2)头部及输入框处于正常文档流,且所占可视区域变大,底部元素 fixed

ios 的 height 没有发生变化,页面可以滚动;

android 页面高度变小,但为了使正常文档流的元素可以正常显示,页面可以上下滚动,fixed 元素的 bottom 属性的基线为键盘;

(3)头部处于正常文档流,输入框脱离正常文档流 fixed bottom 定位


(上面为了便于观察,将输入框包裹元素的背景设置了透明度)

ios 的 height 没有发生变化,且始终保证输入框处于可视区域中;

android 页面高度变小,页面不可滚动,fixed 输入框 bottom 属性的基线为键盘;

5. 小结

  1. 在 ios 中,无论何种布局,为了使输入框展示在可视区域中,键盘弹出时,页面会向上滚动,该过程与 Element.scrollIntoViewIfNeeded() 方法(将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域)产生的效果一致;且高度始终不变,页面可滚动。
  2. 在 android 中,键盘唤起后,页面可滚动与否由其处在正常文档流中的元素决定:如果正常文档流中的元素可全量展示,页面不可滚动,否则页面支持滚动;
  3. 在 android 中,键盘唤起后,fixed 元素的基准会发生变化:根据 bottom 定位的元素,其基线变为键盘上部;根据 top 定位的元素,仍然根据页面顶部,因此为照顾正常文档流及 fixed 元素的用户体验,有的元素可根据顶部定位,有的可以根据底部定位。

在了解清楚 h5 中键盘的弹出收起的性质后,在处理兼容性问题会容易很多。同时也可使用Element.scrollIntoViewIfNeeded() 方法辅助解决问题(比如在切换不同的输入法时,可能导致有用信息被遮挡的情况)优化体验。

作者:阿里巴巴TXD
链接:https://juejin.im/post/5c6d1c8b6fb9a049de6df441
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

H5 键盘兼容性小结的更多相关文章

  1. h5 ios输入框与键盘 兼容性优化

    起因 h5的输入框引起键盘导致体验不好,目前就算微信.知乎.百度等产品也没有很好的技术方案实现,尤其底部固定位置的输入框各种方案都用的前提下体验也并没有很好,这个问题也是老大难问题了.目前在准备一套与 ...

  2. 【H5】344- 微信 H5 页面兼容性解决方案

    点击上方"前端自习课"关注,学习起来~ 最近给公司微信公众号,写了微信h5业务页面,总结分享一下前端开发过程中的几个兼容性坑,项目直接拿的公司页面,所以下文涉及图片都模糊处理了. ...

  3. 近期H5项目开发小结

    前言:2016差不多又过了半啦,最近参与了公司好几个h5项目(严格来说,也只能算是推广页面活动).主要是新品牌的推广需要,当然也有给公司以前老客户做的案例.今天主要总结下为新品牌开发的2个h5推广:就 ...

  4. H5键盘事件处理

    if (/Android/gi.test(navigator.userAgent)) { const innerHeight = window.innerHeight; window.addEvent ...

  5. h5页面适配小结

    大概是去年的7月想写这个内容去加深自己的理解.现在终于回来补上这篇入门小结了. 1.问题描述 适配的目标:在不同尺寸的手机设备上,页面“相对性的达到合理的展示(自适应)”或者“保持统一效果的等比缩放( ...

  6. 可编辑DIV与移动端软键盘兼容性问题汇总

    此文复现的所有兼容性问题均为以下情况: 1. 腾讯X5内核 2. 全屏webview 问题如下: 1. IOS12 中软键盘弹出导致页面顶部截断,并且无法恢复. 解决方法:添加交互事件,调用本地方法, ...

  7. IE兼容性小结(IE7及以上版本)

    缘由 在急速的互联网时代,原本ie系列的低版本浏览器就该淘汰了.可偏偏还是有很多xp系统ie7.8浏览器,这有让网站甚是苦逼.练就了一套新技术,原本以为能大展身手,可却在ie阵容中认怂了,不得不规规矩 ...

  8. iOS Android中 h5键盘遮挡输入框的问题和解决方案

    问题发现:在 Android 部分机型 和 iOS部分系统下 键盘会出现遮挡输入框的情况(壳内).问题解决: Android 经过测试,Android 的6.0版本以上均会出现改问题,归根到底是之前的 ...

  9. 解决ie8下h5元素兼容性的问题

    HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页面显得非常简单. HTML5的新标签元素有: <header&g ...

随机推荐

  1. P3919 【模板】可持久化数组(可持久化线段树/平衡树)

    题目描述 如题,你需要维护这样的一个长度为 N  的数组,支持如下几种操作 在某个历史版本上修改某一个位置上的值 访问某个历史版本上的某一位置的值 此外,每进行一次操作(对于操作2,即为生成一个完全一 ...

  2. Maximum Subarray - LeetCode

    目录 题目链接 注意点 解法 小结 题目链接 Maximum Subarray - LeetCode 注意点 最大值有可能是正负数交替着出现 解法 解法一:一次遍历即可.当sum小于0的时候就重新开始 ...

  3. 【bzoj1833】 ZJOI2010—count 数字计数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1833 (题目链接) 题意 求在${[a,b]}$范围内整数中,每个数码出现的次数. Solution ...

  4. C#线程篇---解答线程之惑(2)

    我们都知道,在这个行业,追求的就是用最少的时间学最多的知识,这是我写这个系列最想达到的目标,在最快的时间内,帮助更多的人学习更多的线程知识. 前一篇,讲述了线程基础,给大家铺垫了一个基础,这一篇着重介 ...

  5. std::function 使用_

    #include <iostream> #include <functional> //函数指针写法 typedef int(*FuncPoint)(const int& ...

  6. boost::asio::deadline_timer(理解)

    并发与并行: 并发和并行从宏观上来讲都是同时处理多路请求的概念.但并发和并行又有区别,并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔内发生. 1.Timer.1 - 使 ...

  7. 使用kafka消息队列解决分布式事务(可靠消息最终一致性方案-本地消息服务)

    微服务框架Spring Cloud介绍 Part1: 使用事件和消息队列实现分布式事务 本文转自:http://skaka.me/blog/2016/04/21/springcloud1/ 不同于单一 ...

  8. (四)关于读文件的结束的判别方法(EOF和feof)以及区别

    关于读文件的时候判断文本是否读完的方式一般可以通过EOF,一般宏定义为-1.因为ASCII码中不可能出现-1. 当以文本形式读取文件内容, 读入的字符值等于EOF时, 表示读入的已不是正常的字符而是文 ...

  9. 【Asp.net入门07】第一个ASP.NET 应用程序-创建数据模型和存储库

    1.理解概念 先理解一下两个概念. 模型 模型是指数据的结构类型,以及可调用的方法.对面向对象编程方法来说,其实就是类.模型类就是一个描述数据的类.只有把数据按一定方式描述出来,我们才能在程序中方便地 ...

  10. Tomcat性能调优及JVM内存工作原理

    Java性能优化方向:代码运算性能.内存回收.应用配置. 注:影响Java程序主要原因是垃圾回收,下面会重点介绍这方面 代码层优化:避免过多循环嵌套.调用和复杂逻辑.Tomcat调优主要内容如下:1. ...