h5虚拟键盘,h5调用手机键盘

  h5虚拟键盘,h5调用手机键盘

  前言

  最近在做H5聊天项目,踩了其中一个大洞:输入框获得焦点,软键盘弹出,要求输入框吸附(或顶)在输入法框上。需求很明确,看似简单,其实不然。从一些测试的模型中,发现存在以下问题:

  在Android和IOS上,已知软键盘的上下状态有区别,页面的webview也不一样。在IOS12,微信版本v6.7.4及以上,输入框获得焦点,键盘弹出,页面(webview)整体向上滚动。键盘放好之后,没有回到原来的位置,导致键盘原来的位置是空白的。在IOS上,使用第三方输入法,高度计算有偏差,导致部分输入法弹出,遮挡了部分输入框。有些浏览器使用了一些操作技巧,但是输入框还是被输入法挡住了。逐一探讨上述问题的解决方法。

  获知软键盘弹起和收起状态

  知道软键盘是向上还是向下是很重要的,这是后续兼容处理的前提。而H5并没有直接监控软键盘的原生事件,只是通过软键盘弹起或者折叠起来,触发了对页面其他方面性能的间接监控,拯救了国家。而且在IOS和Android上的表现也不太一样。

  IOS 软键盘弹起表现

  在IOS上,输入框(input、textarea或rich text)获得焦点,键盘弹出,页面(webview)不压缩,或者高度(height)不变,但整个页面(webview)向上滚动,最大scrollTop为软键盘的高度。

  Android 软键盘弹起表现

  同样,在Android上,输入框获得焦点,键盘弹出,但是webview的高度会改变。一般来说,高度就是可视区域的高度(原来的高度减去软键盘的高度),只是webview本身因为页面内容被拉伸而无法滚动。

  IOS 软键盘收起表现

  当软键盘上的“折叠”按钮被触发或者输入框外的页面区域被触发时,输入框失去焦点,软键盘被折叠。

  Android 软键盘收起表现

  当输入框外的区域被触发时,输入框失去焦点,软键盘收起。但当键盘上的折叠键键盘被触发时,输入框不会失去焦点,软键盘会折叠。

  监听软键盘弹起和收起

  基于上述键盘弹出和折叠在IOS和Android上的不同表现,我们可以分别对软键盘的弹出和折叠进行如下监控:

  在IOS上,听输入框的焦点事件知道软键盘弹出,听输入框的模糊事件知道软键盘折叠起来。在Android上,监控webview的高度会发生变化。当高度变小时,软键盘会弹出,否则,软键盘会收起。//确定设备类型var judge device type=function(){ var ua=window . navigator . user agent . tolocallelower case();var isIOS=/iphoneipadipod/。测试(ua);var isAndroid=/android/。测试(ua);return { isIOS: isIOS,Android:isa Android } }()//监听输入框函数的软键盘弹出和折叠事件Listen Keybold($ input){ if(judged device type . isIOS){//IOS键盘弹出:IOS和Android输入框获取焦点键盘弹出$ input.addeventlistener (focus),function () {console.log (iOS键盘弹出!);//IOS键盘弹出后运行},false) //IOS键盘折叠:IOS点击输入框或折叠按钮外的区域,输入框失去焦点,键盘折叠,$ input.addeventlistener (blur ,()={console.log (iOS键盘折叠!);iOS键盘收起后的操作})} //Andriod键盘收起:Andriod键盘在弹出或收起时页面高度会发生变化,所以可知键盘收起是如果(判断设备类型。isan droid){ var origin height=document . document element . client height document . body . client height;window . addevent listener( resize ,function(){ var resize height=document . document element . client height document . body . client height;if(origin height resize height){ console . log( Android键盘不在!);//安卓键盘折叠后操作} else {console.log(安卓键盘弹出!);Android键盘弹出后的操作} originHeight=resizeHeight},false)} } var $ inputs=document . query selector all(。输入’);for(var I=0;I $输入.长度;I){ listenKeybord($ inputs[I]);}弹起软键盘始终让输入框滚动到可视区

  有时候,我们会制作一个有很多输入项的输入表单。输入框获得焦点,软键盘弹出。当输入框位于页面底部时,在IOS上,整个webview会向上滚动一定距离,这样获得焦点的输入框会自动处于可见区域,但在Android上不是这样,只会改变页面的高度,而不是滚动到当前焦点元素到可见区域。

  由于上面已经实现了对IOS和Android键盘弹出和折叠的监控,这里只需在Android键盘弹出后将焦点元素(scrollIntoView())滚动到可视区域即可。想看效果,可以戳这里。

  //获取焦点元素并滚动到可见区域函数Active Element ScrollintoView(Active Element,Delay){ var editable=Active Element . Get attribute( content editable )//输入框、textarea或rtf文本没有将元素滚动到可见区域if(Active Element . tagname== input )Active Element . tagname== TEXTAREA editable== editable){ set time out(Function(){ Active Element . ScrollintoView();},延迟)}}//.Android键盘弹出后操作ActiveElementScrollintoView($ input,1000);//.唤起纯数字软键盘

  上面的表单输入框要求你输入一个电话号码,会弹出一个数字软键盘是这样的。由于软键盘兼容,请插入此处。较好的解决方案如下:

  p请输入你的手机号码/pin put type= tel no validate= no validate pattern=[0-9]* class= input type= tel ,这是HTML5的一个属性,表示输入框类型是电话号码。在Android和IOS中也差不多,会有数字小键盘,但也会有字母,略显多余。Pattern=[0-9],Pattern用于验证表单的输入内容。通常是HTML5的类型属性,比如email,tel,number,data class,url等。已经有了自己简单的数据格式验证功能。有了图案的加入,前面部分的验证更加简单高效。IOS中只有[0-9]\*可以调节九宫格数字小键盘,\d无效,Android 4.4及以下(含X5内核),两者都可以调节数字小键盘。Novalidate=novalidate ,Novalidate属性规定表单在提交时不会被验证。因为模式验证兼容性差,不允许验证,只会调用纯数字键盘,js来做验证。

  兼容 IOS12 + V6.7.4+

  如果在IOS12和V6.7.4版本中用微信浏览器打开上表输入的演示,你会惊讶地发现,键盘折叠起来后,原本通过滚动向上推的页面并没有回到底部位置,导致原来的键盘弹出位置被“清空”。

  其实这是苹果的IOS bug,会出现在所有打包Xcode10的IOS12设备上。官方微信已经给出了解决方案,软键盘放好后把页面(webview)滚回窗口底部(clientHeight位置)即可。修复完以上表格,进入demo戳这里。

  Console.log(IOS键盘不在了!);//微信浏览器6.7.4版IOS12会出现。键盘折叠起来后,视图被向上推而不是向下。VarweChatInfo=window . navigator . user agent . match(/micro messenger \/([\ d \.])/I);如果(!微信Info)返回;var we chat version=we chat info[1];var version=(navigator . appversion)。匹配(/OS (\d )_(\d )_?(\d)?/);if ( wechatVersion.replace(/\)。/g, )=674 version[1]=12){ window . scroll to(0,math . max(document . body . client height,document . document element . client height));}兼容第三方输入法

  话虽如此,事实上,H5聊天输入框的漏洞已经被填补了一大半。我们先来看看聊天输入框的基本HTML结构。

  class= chat _ _ content div class= chat _ _ content div p/div!-省略几千行聊天内容-/div div class= input _ _ content div class= input content editable= true /div button send/button/div style

  /*省略部分样式*/。聊天_ _内容{高度:calc(100%-40px);边距-底部:40px溢出-y:自动;溢出-x:隐藏;}.input _ _ content { display:flex;高度:40px位置:绝对;左:0;右:0;底部:0;对齐-项目:居中;}/*省略一些样式*/很简单,就是划分内容区和输入区,输入区绝对定位。按照上表输入demo的做法,确实大部分安卓浏览器都没问题,但是测试在IOS上,UC浏览器配合原生输入法和第三方输入法(比如搜狗输入法),输入框会完全被屏蔽;QQ浏览器或者微信浏览器,配合第三方输入法,输入框会被遮住一半;百度浏览器带第三方输入法的输入框也将被完全覆盖。可以在相应的浏览器中访问查看效果。

  在UC浏览器上,软键盘弹出后,浏览器上方标题栏的高度有一种降高延时的动态效果,导致webview向下滚动一点,底部输入框滚动到不可见区域。

  对于第三方输入法来说,猜测本身是因为输入法面板弹出后高度计算错误,导致webview初始滚动定位错误。其实这两点都是webview滚动不到位造成的。可以让软键盘弹出,让焦点元素再次滚动到可视区域,强制webview原地滚动。

  Console.log(Android键盘弹出!);activeElementScrollIntoView($ input,1000);兼容 Android 小米浏览器的 Hack 方案

  在Android的小米浏览器上,应用上述方案,发现聊天输入框依然被完全屏蔽,scrollIntoView()依然不动。所以猜测,其实就是滚动到最后,软键盘弹出,实现的页面高度大于可视区域的高度,这样软键盘弹出后只能强行增加页面高度,才能显示输入框。以上兼容第三方输入法,观看效果可以戳这里。

  //Andriod键盘折叠:Andriod键盘在弹出或者向上折叠时页面高度会发生变化,并以此为基础得知键盘折叠if(判断设备类型。isan droid){ var origin height=document . document element . client height document . body . client height;window . addevent listener( resize ,function(){ var resize height=document . document element . client height document . body . client height;if(origin height resize height){ console . log( Android键盘不在!);//修复了小米浏览器if下输入法仍然遮挡输入框的问题(判断设备类型。ismiubrowser){ document . body . style . margin bottom= 0px ;}} else {console.log(Android键盘弹出!);//修复了小米浏览器if下输入法仍然遮挡输入框的问题(判断设备类型。ismiubrowser){ document . body . style . margin bottom= 40px ;} activeElementScrollIntoView($ input,1000);} originHeight=resizeHeight},false)}总结

  H5,前面的路很长,有很多坑,所以我们需要继续努力。了解软键盘弹出页面在IOS和Android上的性能差异是前提,其次是将焦点元素滚动到可视区域,还要考虑到第三方输入法和部分浏览器的差异。

  这就是本文的全部内容。希望对大家的学习和支持有帮助。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: