前言

在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上。

说明白简单点就是,输入框被键盘挡住了。而且在原生中,输入框应该正好在输入键盘上,但是h5 没有这种体验,那么我们需要自己实现。

再次用图说明情况。

情况一:

键盘挡住了,输入框。

情况二:

红色代表有滚动条,输入框,没有正好卡在下面,用户体验不好,同样输入的时候不能滑动体验也不好。

开工

正确情况:

要做的其实就是两步:

第一步,动态改变可滑动的高度,就是在输入的时候可以通过滑动看到下面蓝色的部分:

第二部,需要修改滚动距离:

也就是需要滚动多少,输入框才刚好在键盘下。那这个怎么移动呢?我们该如何滚动才能完成呢?



计算滚动的距离,其实就是计算输入框移动的距离。

这个问题就简单了,分两种情况,其实就一种哈。

假如输入框在上面:

就是我们滑动块的底部到顶部的距离-输入框底部到顶部的距离

加入输入框在键盘下面:

就不画了,也是我们滑动块的底部到顶部的距离-输入框底部到顶部的距离,只不过我们得到的是负数,正好我们对应了我们滑动的方向。

好的,现在我们要做的就是实现这两步。

如何修改键盘弹起的高度?

我们只要知道键盘的高度和屏幕的高度即可。

屏幕高度,我们不需要去知道,因为需要修改样式,直接100vh-键盘高度即可。

键盘的高度如下:

window.addEventListener("keyboardWillShow", this.keyboardShowCallback);

在keyboardShowCallback有个参数是e:

public keyboardShowCallback = (e) => {

e.keyboardHeight;// 取得键盘的高度

})

在这里,因为我的滑动块是全屏的,那么我可以这样:

public keyboardShowCallback = (e) => {

//page 是我当前页面的滑动块,100vh就是屏幕高度

page.setAttribute('style', 'height:calc(100vh - ' + e.keyboardHeight + 'px) !important;z-index:150;');

})

那么如何获取当前正在输入的输入框,只要获取当前焦点的位置 document.activeElement:

var rect = document.activeElement.getBoundingClientRect();

通过getBoundingClientRect 获取到输入框各个位置到屏幕的距离:

我们需要的是输入框的底部,那么就是: rect.bottom;

那么我们计算滑动距离就是:

scrolldiv//表示可滑动的元素

var scrolldivrect = scrolldiv.getBoundingClientRect();

var addScrollTop = rect.bottom - scrolldivrect.bottom;

scrolldiv.scrollTop = scrolldiv.scrollTop + addScrollTop;

接下来就是键盘收起来的时候恢复:

// 监听键盘隐藏
window.addEventListener("keyboardWillHide", this.keyboardHideCallback);
//恢复事件
page.setAttribute('style', 'height: 100vh !important;z-index:120;');

在这里,其实就已经实现效果了,那么这时候会在一些平台上遇到一些问题。

遇到的问题

ios 光标乱飘

造成原因,是因为我们设置滑动了,在低版本如ipad mini3上会出现光标和输入框不对应。

那么这个时候,我继续输入,或者我点一下其他地方光标又正常了。

这时候给了我线索,我需要重绘这个input 就行。那么如何重新绘制呢?我们无法操作啊。但是我们知道如果改变某些样式是会触发重绘过程,具体查看标准。

code 如下:

var activeElement = document.activeElement; //取得focus的dom元素
setTimeout(function () {
if (activeElement) {
if (activeElement.nodeName == "TEXTAREA" || activeElement.nodeName == 'INPUT') { //如果是input或textarea
if ((Object)(activeElement).style.textShadow === '') {
(Object)(activeElement).style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改变某个不可见样式,触发dom重绘
} else {
(Object)(activeElement).style.textShadow = '';
}
}
}
}, 0);

收起键盘出现白屏,在低版本上连续弹起键盘白屏无消失

这个问题得回到设计的根源上。



在我们收起键盘的时候,我们就会让红色部分为100%;

键盘收齐向下,然后红色向下,如果键盘收起速度,大于红色向下增大的速度,就会出现一点白,然后消失。

怎么解决呢?



红色部分是我们滚动的部分,蓝色是content,这时候让content设置为100%vh,这时候马上可视区域就会马上重绘。

在keyboardHideCallback 中

var num = Math.random() * 99;
ionContent.setAttribute('style', 'height: 100vh !important;z-index:' + num + '');

当然,然后要在keyboardShowCallback 中设置为100%,如何不设置回去,键盘弹起就会挡住输入框:

var num = Math.random() * 99;
ionContent.setAttribute('style', 'height: 100% !important;z-index:' + num + '');

总结

如果要兼容一些低版本,需要主动触发去让一些区域刷新,这些可以解决大部分白屏问题,或者其他疑难杂症(如光标漂移)。

键盘优雅弹出与ios光标乱飘解决方案的更多相关文章

  1. Android 判断软键盘弹出并隐藏的简单完美解决方案

    最近项目中有一个编辑框,下面是个ListView.在触发编辑框弹出软键盘后,ListView还能滑动,并且ListView的item还能响应单击.这样的体验效果很不好.于是便想在滑动或单击item时判 ...

  2. vue 监听手机键盘是否弹出及input是否聚焦成功

    //定义移动端类型 function pageStats() { let u = navigator.userAgent, app = navigator.appVersion; let obj = ...

  3. 关于Android 打开新的Activity 虚拟键盘的弹出与不弹出

    关于Android 打开新的Activity 虚拟键盘的弹出与不弹出 打开Activity 时  在相应的情况 弹出虚拟键盘 或者 隐藏虚拟键盘 会给用户非常好的用户体验 , 实现起来也比较简单 只需 ...

  4. 关于ios8模拟器不能输入中文问题以及软键盘不弹出问题

    在Xcode菜单栏中   Product->scheme->Edit Scheme->Options->Application Region改为中国,就可以输入中文了, 如果软 ...

  5. Android 另类方法监听软键盘的弹出收起事件

    http://www.cnblogs.com/csonezp/p/5065624.html 最近做的项目碰到个问题,a界面是fragment+recyclerview,b界面带个edittext,并且 ...

  6. Android中检测软键盘的弹出和关闭

    Android系统并没有提供明显的API来监听软键盘的弹出和关闭,但是在某些情况下我们还是有办法来检测软键盘的弹出和关闭. 从StackOverflow找到了一个不错的方法.但是这种只适用于在mani ...

  7. Android: View换切后,无法正常设置焦点或切换后TextView的虚拟键盘不弹出

    边学.边测试,花了三天时间完工一个小应用. 遇到很多问题,但最终还是解决了. 我的手机是Android2.2版,所以我也在是2.2版环境下学习,开发. 1. 在同一个Activity中的不同View( ...

  8. android软键盘弹出引起的各种不适终极解决方案

    android软键盘弹出引起的各种不适终极解决方案 以下描述如何解决ListView高度小于0时出现的UI问题. 创建RelativeLayout的子类TxrjRelativeLayout publi ...

  9. iOS 自定义键盘ToolBar(与键盘的弹出、收起保持一致)

    1.监听键盘改变的通知 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyBoardWillCha ...

随机推荐

  1. 2015-2016 ACM-ICPC Southwestern Europe Regional Contest (SWERC 15)

    C. Canvas Painting 合并果子. E. Wooden Signs \(dp(i,l,r)\)表示第\(i\)块木板的长度区间为\([l,r]\)的方案数,根据题意,\(l\)或\(r\ ...

  2. Python--day45--pymysql模块初识以及SQL注入

    pymysql模块学习路径:增删改的时候一定要conn.commit() pymysql模块实现登录功能: import pymysql user = input("username:&qu ...

  3. $_GET $_POST $_REQUEST

    <form action="__APP__/View/editArticle?id=5" method="GET"> <form>表单提 ...

  4. Vue 项目构建完成 ----发布项目

    发布项目 cmd  命令行 npm run build      执行打包文件 完成后就会有  3 个文件夹    分别是: 文件夹 :build     config      dist    in ...

  5. H3C RIP协议概述

  6. linux模块参数

    驱动需要知道的几个参数因不同的系统而不同. 从使用的设备号( 如我们在下一章见到的 ) 到驱动应当任何操作的几个方面. 例如, SCSI 适配器的驱动常常有选项控制标记命令队列 的使用, IDE 驱动 ...

  7. js基础——变量、作用域、内存

    1.new关键字创建的是引用类型: eg. var box = new Object();      box.name = "Linda";//引用类型添加属性没问题     al ...

  8. ipv6现状,加英文的中括号访问, ipv6测试http://test-ipv6.com

    加英文的中括号就可以,如[2001:4998:c:e33::1004],我发现这是yahoo首页.但并不是所有IPv6网站都可以通过IPv6地址访问,跟IPv4一样,网站服务器端可以只绑定域名,不接受 ...

  9. sci,ei,istp三大科技文献检索系统

    印刷版(SCI) 双月刊 ,500种 联机版(SciSearch) 周更新 ,600种 光盘版(带文摘)(SCICDE) 月更新 ,500种(同印刷版) 网络版(SCIExpanded) 周更新 ,6 ...

  10. Linux 内核VLB 总线

    另一个对 ISA 的扩展是 VESA Local Bus(VLB) 接口总线, 它扩展了 ISA 连接器, 通过 添加第 3 个知道长度的槽位. 一个设备可只插入这个额外的连接器(不用插入 2 个关联 ...