键盘优雅弹出与ios光标乱飘解决方案

摘要:
前言在移动开发中,我们会遇到这样的情况。例如,当底部有一个输入框时,我们将弹出输入框,输入框将不在输入键盘上。为了清楚起见,输入框被键盘挡住了。如何修改键盘的高度?我们遇到的问题是,ios光标是随机浮动的,因为我们将其设置为滑动。在较低版本(如ipadmini3)中,光标与输入框不对应。

前言

在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上。
说明白简单点就是,输入框被键盘挡住了。而且在原生中,输入框应该正好在输入键盘上,但是h5 没有这种体验,那么我们需要自己实现。
再次用图说明情况。
情况一:
键盘优雅弹出与ios光标乱飘解决方案第1张

键盘挡住了,输入框。

情况二:

键盘优雅弹出与ios光标乱飘解决方案第2张

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

开工

正确情况:

键盘优雅弹出与ios光标乱飘解决方案第3张

要做的其实就是两步:

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

键盘优雅弹出与ios光标乱飘解决方案第4张

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

也就是需要滚动多少,输入框才刚好在键盘下。那这个怎么移动呢?我们该如何滚动才能完成呢?
键盘优雅弹出与ios光标乱飘解决方案第5张
计算滚动的距离,其实就是计算输入框移动的距离。
这个问题就简单了,分两种情况,其实就一种哈。
假如输入框在上面:
键盘优雅弹出与ios光标乱飘解决方案第6张

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

加入输入框在键盘下面:

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

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

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

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

屏幕高度,我们不需要去知道,因为需要修改样式,直接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上会出现光标和输入框不对应。

键盘优雅弹出与ios光标乱飘解决方案第7张

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

这时候给了我线索,我需要重绘这个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);

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

这个问题得回到设计的根源上。
键盘优雅弹出与ios光标乱飘解决方案第8张
在我们收起键盘的时候,我们就会让红色部分为100%;
键盘收齐向下,然后红色向下,如果键盘收起速度,大于红色向下增大的速度,就会出现一点白,然后消失。

怎么解决呢?
键盘优雅弹出与ios光标乱飘解决方案第9张
红色部分是我们滚动的部分,蓝色是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光标乱飘解决方案》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Quartz2D简单使用(二)深入理解xLua基于IL代码注入的热更新原理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

安卓 验证码输入框InputCode(同时支持密码输入)

继承EditText实现自定义验证码边框InputCode 1、可修改边框焦点颜色及文字颜色大小,同时还支持自定义图片。 2、键盘密码可随机仅供参考。 演示:            InputCodeEditText.java 自定义控件 package com.dzw.inputcode; import android.content.Context...

第二百一十三节,jQuery EasyUI,NumberBox(数值输入框)组件

jQuery EasyUI,NumberBox(数值输入框)组件 功能:只能输入数值,和各种数值的计算 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 NumberBox(数值输入框)组件的使用方法,这个组件依赖 于 ValidateBox(验证框)组件。 一.加载方式 class 加载方式...

HTML文本框样式大全

输入框景背景透明:<input style="background:transparent;border:1px solid #ffffff"> 鼠标划过输入框,输入框背景色变色:<INPUT value="Type here" NAME="user_pass" TYPE="text" SIZE="29" onmouseover="thi...

html 输入框只允许输入数字

要想限制文本框只能输入数字,你可以用Html5的标签就可以解决: 为input标签添加样式 type="number"即可。 // 限制输入框的数字输入范围 var strPri = document.getElementById("Pritxt").value; if(strPri < 1 || strPri > 999) {...

selenium 难定位元素,时间插件,下拉框定位,string

1.元素定位 ID定位元素: findElement(By.id(“”)); 通过元素的名称定位元素: findElement(By.name(“”)); 通过元素的html中的位置定位元素: findElement(By.xpath(“”)); 通过元素的标签名称定位元素: findElement(By.tagName(“”)); 通过元素的链接名称...

后台界面设计之表单设计规范参考

前言 在后台界面设计之表格设计规范参考一文中,我们对表格中内容的布局、数据的展示、操作项的罗列进行了详细的讲解,本文将对表单的设计规范做一个参考性的建议。 表单是中后台系统最常见的元素模块之一,承载了各个流程中信息数据的录入使命。提高信息数据录入的效率可以加速用户达成目标的时间与降低操作成本。 一般要求在录入前尽可能的使用户理解信息录入的目的与预测并判断需...