react在安卓中输入框被手机键盘遮挡问题的解决方法


Posted in Javascript onSeptember 03, 2018

前言

React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

本文主要介绍了关于react在安卓输入框被键盘遮挡的相关内容,分享出来动大家参考学习,下面话不多说了,来一起看看详细的介绍吧

问题概述

今天遇到了一个问题,在安卓手机上,当我要点击输入“店铺名称”时,手机软键盘弹出来刚好把输入框挡住了;挡住就算了,关键是页面还不能向上滑动,整个手机窗口被压为原来的二分之一左右;

react在安卓中输入框被手机键盘遮挡问题的解决方法

然后

然后找了一些方案,不过不大适用,或者是有点麻烦;所以需要整合一下,

首先,我想一下我要实现的效果(2018/9/3补充:评论区有更加简单的实现方法)

想要实现的效果

react在安卓中输入框被手机键盘遮挡问题的解决方法

如图,当手机键盘出现时,页面是可以自由滚动的,而且当前聚焦的输入框往红线处靠齐,这样就刚好在剩下的窗口的垂直正中间,这样就不会出现输入框被挡住,看不到自己输入的内容了 ;

第一步,使屏幕压小时,页面内容可以滚动查看

如下图所示,黑色框代表屏幕,蓝色框代表页面大小,当屏幕被压小时,页面内容必须保持原来的高度:

react在安卓中输入框被手机键盘遮挡问题的解决方法

实现原理,页面一进来时,我就获取窗口的高度,给最外层的div设置一个最小高度,这样就算窗口压小了,页面还能维持原来的高度,可以滚动浏览:

let initWindowHeight=window.innerHeight
  let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0]
  wrapDiv.style.minHeight =initWindowHeight+'px'

第二步,滚到红线处

由于我们不能直接知道软键盘什么时候出来,不过软键盘出来的时候窗口高度会缩小,所以我们可以通过监听窗口大小变化事件来判断软键盘是否弹出,比如浏览器窗口高度突然缩小25%以上,那么我们就认为是软键盘出来了,然后我们获取聚焦input距离页面顶部的距离,计算距离红线有多少距离,假设距离是60,那么我们就让页面向上滚动60,这时input就刚刚好到了红线处;

window.onresize=function(){ 
  if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){
   //offset是封装好的一个获取元素距离页面顶部滚动距离的方法
   if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){
    document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4
   }
  }else if(window.innerHeight-initWindowHeight<20){
   document.body.scrollTop=0
  }
 };

完整代码

因为可能有多个页面要调用,所以我把代码放到一个单独的js文件中:

function pageInputScroll() {
 
 let initWindowHeight=window.innerHeight
 setTimeout(() => {
  let wrapDiv=document.getElementsByClassName('animated-router-forward-enter-done')[0]
  //console.log(wrapDiv.style)
  wrapDiv.style.minHeight =initWindowHeight+'px'
   
  }, 500);
  //由于我们不能直接知道软键盘什么时候出来,不过软键盘出来的时候窗口高度会缩小,所以我们可以通过监听窗口大小变化事件来判断软键盘是否弹出
 window.onresize=function(){ //如果浏览器窗口高度缩小25%以上,就认为是软键盘出来了
  if(initWindowHeight-window.innerHeight>initWindowHeight/4&&document.querySelectorAll(':focus').length>0){
   if(offset(document.querySelectorAll(':focus')[0]).top>initWindowHeight/4){
    document.body.scrollTop=offset(document.querySelectorAll(':focus')[0]).top-initWindowHeight/4
   }
  }else if(window.innerHeight-initWindowHeight<20){
   document.body.scrollTop=0
  }
  
 };
}
function offset(element) {
 var offest = {
  top: 0,
  left: 0
 };
 
 var _position;
 
 getOffset(element, true);
 
 return offest;
 
 // 递归获取 offset, 可以考虑使用 getBoundingClientRect
 function getOffset(node, init) {
  // 非Element 终止递归
  if (node.nodeType !== 1) {
   return;
  }
  _position = window.getComputedStyle(node)['position'];
 
  // position=static: 继续递归父节点
  if (typeof(init) === 'undefined' && _position === 'static') {
   getOffset(node.parentNode);
   return;
  }
  offest.top = node.offsetTop + offest.top - node.scrollTop;
  offest.left = node.offsetLeft + offest.left - node.scrollLeft;
 
  // position = fixed: 获取值后退出递归
  if (_position === 'fixed') {
   return;
  }
 
  getOffset(node.parentNode);
 }
}

export {pageInputScroll};

在react页面中引入js并调用:

import {pageInputScroll} from '../../util/pageInputScroll'
 ......
 componentDidMount(){
  pageInputScroll()
 }

如果只是想在安卓下使用,可以加一个判断:

if(/Android/i.test(navigator.userAgent)){
  pageInputScroll()
 }

效果动图

我在pc端的谷歌浏览器模拟一下实现的效果:

react在安卓中输入框被手机键盘遮挡问题的解决方法

备注

offset()方法是使用js实现类似jquery的offset()的一个方法,参考自:原生js实现offset方法

总结:

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
基于jQuery的图片左右无缝滚动插件
May 23 Javascript
javascript实例--教你实现扑克牌洗牌功能
May 15 Javascript
修改或扩展jQuery原生方法的代码实例
Jan 13 Javascript
JavaScript类继承及实例化的方法
Jul 25 Javascript
多个js毫秒倒计时同时进行效果
Jan 05 Javascript
再次谈论React.js实现原生js拖拽效果引起的一系列问题
Apr 03 Javascript
div实现自适应高度的textarea实现angular双向绑定
Jan 08 Javascript
JavaScript的六种继承方式(推荐)
Jun 26 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
Feb 04 Javascript
vue.js 中使用(...)运算符报错的解决方法
Aug 09 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
Sep 12 Javascript
vue实现文字横向无缝走马灯组件效果的实例代码
Apr 09 Javascript
Vue 中对图片地址进行拼接的方法
Sep 03 #Javascript
VUE预渲染及遇到的坑
Sep 03 #Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
Sep 03 #Javascript
vue的style绑定background-image的方式和其他变量数据的区别详解
Sep 03 #Javascript
vue完成项目后,打包成静态文件的方法
Sep 03 #Javascript
vue填坑之webpack run build 静态资源找不到的解决方法
Sep 03 #Javascript
webpack4 处理CSS的方法示例
Sep 03 #Javascript
You might like
虚拟主机中对PHP的特殊设置
2006/10/09 PHP
PHP数据库调用类调用实例(详细注释)
2012/07/12 PHP
gd库图片下载类实现下载网页所有图片的php代码
2012/08/20 PHP
模板引擎smarty工作原理以及使用示例
2014/05/25 PHP
ThinkPHP之用户注册登录留言完整实例
2014/07/22 PHP
在win7中搭建Linux+PHP 开发环境
2014/10/08 PHP
PHP curl伪造IP地址和header信息代码实例
2015/04/27 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
Android AsyncTack 异步任务实例详解
2016/11/02 PHP
php实现批量上传数据到数据库(.csv格式)的案例
2017/06/18 PHP
laravel中短信发送验证码的实现方法
2018/04/25 PHP
使用laravel的migrate创建数据表的方法
2019/09/30 PHP
基于jquery的修改当前TAB显示标题的代码
2010/12/11 Javascript
jQuery新闻滚动插件 jquery.roller.js
2011/06/27 Javascript
DOM 事件流详解
2015/01/20 Javascript
JS实现单行文字不间断向上滚动的方法
2015/01/29 Javascript
ECMAScript6中Set/WeakSet详解
2015/06/12 Javascript
基于jQuery实现仿QQ空间送礼物功能代码
2016/05/24 Javascript
简单实现nodejs上传功能
2017/01/14 NodeJs
vue通过滚动行为实现从列表到详情,返回列表原位置的方法
2018/08/31 Javascript
如何使用pm2快速将项目部署到远程服务器
2019/03/12 Javascript
微信小程序实现上拉加载功能
2019/11/20 Javascript
跟老齐学Python之print详解
2014/09/28 Python
Python编程实现生成特定范围内不重复多个随机数的2种方法
2017/04/14 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
2018/04/28 Python
Python datetime 如何处理时区信息
2020/09/02 Python
YesStyle美国/全球:购买亚洲时装、美容化妆品和生活百货
2017/01/16 全球购物
波比布朗英国官网:Bobbi Brown英国
2017/11/13 全球购物
Coccinelle官网:意大利的著名皮具品牌
2019/05/15 全球购物
Bonprix法国:时尚、鞋子、家居
2020/12/29 全球购物
颇特女士香港官网:NET-A-PORTER香港
2021/03/08 全球购物
加强作风建设心得体会
2014/10/22 职场文书
2015年世界环境日演讲稿
2015/03/18 职场文书
《倍数和因数》教学反思
2016/02/23 职场文书
golang协程池模拟实现群发邮件功能
2021/05/02 Golang
Python安装使用Scrapy框架
2022/04/12 Python