最近一个项目掉进了移动端的大坑,包括ios下fixed布局,h5唤起键盘等问题,作为一个B端程序员,弱项就是浏览器的兼容性和移动端的适配(毕竟我们可以要求使用chrome),还好这次让我学习了一下相关知识。让我们一起来看一下我怎么挣扎出这个大坑的。

  一、背景

先看一下要做什么,也就是一个文章评论的版块,下面依次有输入框,点赞,收藏等 。大概长下面这个样子:

要求也很常规,吸底,输入评论提交。那么上来就输代码吧。

  二、ios下fixed布局

关于这种吸底操作,上来就直接选用fixed了,这种场景舍他其谁。初步的布局就是这个样子了。(因为我是用的react,jsx的写法粘贴上来简直让人崩溃,就随手写一段代码代表下,勿怪)

 <body>
<div class='top'></div>
<div class='main'></div>
<div class="fix-bottom"></div>
</body>

然后css就不多写了,浏览器上一看还挺想那么回事。然后在ios上就出现了点意外情况。就成了这个样子(希望没有我厂的工友)

就这样被顶起来了。。。。出现问题就算当时要快速解决没有时间去深究,那么下来也要去搞清楚因果,毕竟我们不是为了解决问题而解决问题。一起看下原因

  2.1   ios下fixed失效的原因

  软键盘唤起后,页面的 fixed 元素将失效(ios认为用户更希望的是元素随着滚动而移动,也就是变成了 absolute 定位),既然变成了absolute,所以当页面超过一屏且滚动时,失效的 fixed 元素就会跟随滚动了。

不仅限于 type=text 的输入框,凡是软键盘(比如时间日期选择、select 选择等等)被唤起,都会遇到同样地问题。

  2.2 如何解决

  既然ios就是这个样子,我们只能选择接受现状,只能想办法绕过去了。大致说来两个方向:

  1、既然会变成absolute,索性直接使用absolute算了,

  bottom直接以body作为父元素来进行绝对定位,不过这种网上都不推荐,想来有更多的问题等待修正,前人的经验还是要借鉴的,所以我也没有去尝试,有兴趣的同学可以尝试一下。

  2、不让页面滚动,而是让主体部分自己滚动

  如果fixed的失效,但是页面并没有超过一屏的长度,那么无论absolut或者fixed也没什么差别。顺着这个思路我们回顾一下上面的结构,完全可以让main直接滚着玩就行了。将吸底的元素和主题作为两大容器,主体部分,设置绝对定位,固定在屏幕中间,超出部分就自行滚动,吸底元素就可以自己玩了

大概就是下面这个样子:

 <body>
<div class='warper'>
<div class='top'></div>
<div class='main'></div>
<div>
<div class="fix-bottom"></div>
</body>

对应样式如下:

 .cont-warper{
position: absolute;
width: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */
}
.fix-bottom{
position:fixed;
bottom:0;
width: 100%;
}

这样就能避免上面那个问题了。但是ios下,对于吸底元素而言在屏幕下半部分唤起键盘的时候,会被遮住部分东西,有的资料提到是第三方输入法的toolbar,我看到的现象是吸底元素被遮住了,对于这种情况,我们只好加个监听事件,当唤起键盘的时候,设置scrollTop值,也就是说你不上来,我强迫你上来:

/**
* 唤起键盘,滚动
*/
scrollContent() {
this.interval = setInterval(() => {
this.scrollToEnd();
}, 500)
}
scrollToEnd() {
document.body.scrollTop = document.body.scrollHeight;
}
clearSrcoll() {
clearInterval(this.interval);
}

设置延时切换,input当失去焦点的时候清除。 

   三、h5调用虚拟键盘

  解决了布局问题,下面就开始happy的写功能吧,开始之前,让我们回头继续看下上面的视觉图,是不是感觉少了点什么。我们的提交button呢?一般来说是这样:

  这让我如何下手,还好请教了下老大,作为一个老司机他轻轻的告诉我三个字:网上搜。。。。。

  不扯淡了言归正传,对于这种显然是要利用软键盘上的回车来提交信息的。你最常见的一定是搜索按钮,就是type=‘search’的使用。如果想通过键盘来提交信息,就要把form表单拉出来用用了。

  3.1   键盘提交事件

  一般来说是这样做的,将input包括在form表单内,这样就可以监听submit事件了。如果有人问我是走的ajax不是form表单的话,请记得有个onSubmit事件可以来做一些你想做的事情。代码如下:

 <form onClick={::this.changeInput} onSubmit={this.comment.bind(this, postID)}>
<Input type="text" placeholder="请输入" id='commentInput' value={::this.getVal()} onFocus={::this.scrollContent} onBlur={::this.clearSrcoll}/>
</form>

可能看起来比较蛋疼,没办法react的jsx就是这么蛋疼。上面的那么多事件还真的都有必要。思路如下:

  1、submit事件可以监听到用户软键盘的回车键,对于ajax提交,这里需要我们阻止下form的默认事件,避免form提交的刷新页面的行为

  comment(postID, e) {
e.preventDefault()
// 阻止多次提交
// 你的代码 }

  这样,监听软键盘的提交事件就完成了,但是其他问题又来了  

  3.2  其他区域唤起软键盘

  再看一眼视觉图,不仅仅是点击input可以提交评论,还有一种回复别人评论的需求,点击回复的label也需要唤起键盘来进行操作。

  

移动端而言对于h5的input,focus和blur可以唤起和收起键盘,这样顺理成章的我们可能这样做。给每个回复绑定个事件,点击的时候让input获取焦点即可,代码如下

  

 <div className="comment-resquetion" onClick={this.changeParent.bind(this, comment.comment)}>
回复
</div>
//input获取焦点,并现实被回复人昵称
changeparentComment(val) {
let commentInput = document.querySelector('#commentInput')
commentInput.focus()
this.setState({
parentComment: val
})
}

这样在android下面是可以的,在ios下面又遇到了问题,非input触发的事件是不能唤起键盘的,这样和window.open的限制差不多,只有用户主动的操作才会允许唤起键盘,所以这样是不可以的。

  针对这种情况,我们可以投机取巧一下,既然必须要是input触发的操作,那么回复那里我直接用一个透明的input置于上方不就可以了。

  

 <div className="comment-resquetion" onClick={this.changeParent.bind(this, comment.comment)}>回复<input type='text' className='hide-input'/></div>

  css样式如下:

.comment-resquetion{
position: relative;
font-size: 0.28rem;
color: #3E93C2;
letter-spacing: -1px;
line-height: 0.45rem;
padding: 0.05rem 0 0.15rem 0.32rem; }
.hide-input{
position: absolute;
width: 100%;
height: 0.28rem;
opacity:;
z-index:;
left: 0.32rem;
top:;
}

当点击回复的时候,其实点击的是input,这样就能避开限制唤起软键盘了。

   3.3 关闭键盘

   到这里,以为就这样结束了,结果发现还有个问题,当点击软键盘提交完成的时候,键盘并不能隐藏,这让人有点尴尬,因为点击提交按钮之后,没有主动收起键盘。因为当在软键盘上操作是,io用户的输入行为还在继续,所以不会收起键盘,如果是点击旁边的button提交,就会自动收起了。既然不能主动收起,只能我们手动强制了,在提交事件返回后,可以手动将焦点移除,这里最好做个延时,不然体验有点太快。

 this.commentInput = document.querySelector('#commentInput')
setTimeout(() => {
this.commentInput.blur()
// 评论成功都置空
this.props.changeParent(null)
}, 500)

  到这里这个看起来很小的功能终于结束了,有必要做个总结以供自己及有需要的同学做个参考。

参考文章:

http://efe.baidu.com/blog/mobile-fixed-layout/ 

移动端踩坑之旅-ios下fixed、软键盘相关问题总结的更多相关文章

  1. 微信小程序之mpvue+iview踩坑之旅

    因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...

  2. CentOS7使用tar.gz包安装MySql的踩坑之旅

    由于客户的CentOS服务器没有安装yum工具,只能通过下载tar.gz包安装mysql,于是跟着万能的百度开启了漫漫踩坑之旅: 1.下载mysql-5.6.33-linux-glibc2.5-x86 ...

  3. 我的微信小程序入门踩坑之旅

    前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...

  4. vue+ vue-router + webpack 踩坑之旅

    说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案   老司机可以忽略下面的内容了 1)起因  考虑到数据分离的问题  因为server是express搭的   自然少 ...

  5. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  6. Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...

  7. [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...

  8. EasyTrader踩坑之旅总结

    ​ easytrader是用python写的可以调用主要券商完成自动化炒股的一个软件 ,但我用的是同花顺,在研究过程中,发现同花顺暂时调不通.后来搜索发现thstrade的源码作者说是easytrad ...

  9. vue踩坑之旅 -- computed watch

    vue踩坑之旅 -- computed watch 经常在使用vue初始化组件时,会报一些莫名其妙的错误,或者,数据明明有数据,确还是拿不到,这是多么痛苦而又令人忍不住抓耳挠腮,捶胸顿足啊 技术点 v ...

随机推荐

  1. 蓝桥杯比赛javaB组练习《饮料换购》

    题目如下: 饮料换购 乐羊羊饮料厂正在举办一次促销优惠活动.乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去,但不允许赊账. 请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么 ...

  2. RabbitMQ入门-消息派发那些事儿

    在上篇<RabbitMQ-高效的Work模式>中,我们了解了Work模型,该模型包括一个生产者,一个消息队列和多个消费者. 我们已经通过实例看出消息队列中的消息是如何被一个或者多个消费者消 ...

  3. AVR开发 Arduino方法(一) 端口子系统

    Arduino UNO R3使用的主处理器ATMega328P上有3个8位的输入/输出端口,它们分别是PB,PC和PD.Arduino IDE提供的Blink示例可以帮助我们了解端口的数字输出功能: ...

  4. java 各种去空格的方法

    String str =" dgd fdgd ";   方法一:str = str.trim();//去前后空格 返回:dgd fdgd   方法二:str = str.repla ...

  5. 開源sources

    學了c++已經快有半年光景,感覺在停留在syntax上已經不能感到有所滿足.一下是一些開源資料,難度極高,姑且當作是個人的一個小小wishing list,當作to-do list 般去執行吧. ht ...

  6. [Noi2008]假面舞会

    考试的时候果断放弃,cout<<"-1 -1"骗10分hhh... 这也是图上问题.注意题目意思: ①如果有多个点指向同一个点,那么他们属于同一类别. ②一个点看到的所 ...

  7. 创建 macvlan 网络 - 每天5分钟玩转 Docker 容器技术(55)

    上一节我们准备好了 macvlan 的实验环境,今天在 host1 和 host2 中创建 macvlan 网络 mac_net1: 注意:在 host2 中也要执行相同的命令. ① -d macvl ...

  8. SQL连接、合并、子查询

    连接:连接分为内连接.外连接.交叉连接 内连接和外连接都是在笛卡尔积的基础做一些修改. 合并查询:把两个相似的结果可以用union联合起来. mysql> select id,time from ...

  9. React Native热更新(iOS)-Pushy

    React Native的出现,使的开发iOS代码出现了更便捷的方式.由于RN是使用脚本语言编写的,实现了"解释执行"的方式,而这种执行方式的修改只需替换脚步即可,不需要重新发布程 ...

  10. Hexo快速部署教程

    一直有建立博客的需要,使用过Wordpress动态博客,一直访问速度比较慢,刚开始以为是空间域名的解析的问题,尝试使用Hexo静态博客,部署后感觉速度正常很多,特意发文快速部署教程 准备 本文是在wi ...