Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 319|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-17 15:28:59 | 显示全部楼层 |阅读模式

    前言

    在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上。
    说明白简单点就是,输入框被键盘挡住了。而且在原生中,输入框应该正好在输入键盘上,但是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 + '');
    

    总结

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

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-19 15:29 , Processed in 0.066348 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表