前言

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

说明白简单点就是,输入框被键盘挡住了。而且在原生中,输入框应该正好在输入键盘上,但是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. 2007年NOIP普及组复赛题解

    题目涉及算法: 奖学金:结构体排序: 纪念品分组:贪心: 守望者的逃离:动态规划: Hanoi 双塔问题:递推. 奖学金 题目链接:https://www.luogu.org/problem/P109 ...

  2. H3C PPP显示与调试

  3. 【t002】jam的计数法

    Time Limit: 1 second Memory Limit: 50 MB [问题描述] Jam是个喜欢标新立异的科学怪人.他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世 ...

  4. java 打印流

    (只有两个,PrintWriter和PrintStream) 思考:如果现在要想完成一个字符串或者是boolean型或者是字符型的数据输出使用OutputStream是否方便? 肯定是不方便的,因为O ...

  5. Mail.Ru Cup 2018 Round 2 B. Alice and Hairdresser (bitset<> or 其他)

    传送门 题意: 给出你序列 a,在序列 a 上执行两种操作: ① 0 :查询有多少连续的片段[L,...,R],满足 a[L,...,R] > l: ② 1 p d :将第 p 个数增加 d: ...

  6. QuartusII 13.0的完美破解

    网络上破解QuartusII 13.0软件的方法都不行,最后经过本人总结测试(独创),最终实现了QuartusII 13.0的破解,破解方法如下: 网上常规操作之后,会得到一个“license.dat ...

  7. linux oops 消息

    大部分 bug 以解引用 NULL 指针或者使用其他不正确指针值来表现自己的. 此类 bug 通 常的输出是一个 oops 消息. 处理器使用的任何地址几乎都是一个虚拟地址, 通过一个复杂的页表结构映 ...

  8. H3C 链路聚合的作用

  9. Hamcrest使用

    What is Hamcrest? 什么是Hamcrest?   Hamcrest is a library of matchers, which can be combined in to crea ...

  10. HDU4528 小明捉迷藏 [搜索-BFS]

    一.题意 小明S在迷宫n*m中找大明D和二明E,障碍物X不能走,问你计算是否能在时间t内找到大明和二明 二.分析 2.1与普通的BFS不同,这里可以走回头路,这里应该建立四维的标记数组标记数组,例如v ...