移动端踩坑之旅-ios下fixed、软键盘相关问题总结
最近一个项目掉进了移动端的大坑,包括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、软键盘相关问题总结的更多相关文章
- 微信小程序之mpvue+iview踩坑之旅
因为之前参照微信的原生的文档写过一些小程序的demo,写的过程比较繁琐,后来出了美团的mpvue,可以直接使用vue开发,其他的不作对比,这篇文章记录一下踩坑之旅. 参照mpvue http://mp ...
- CentOS7使用tar.gz包安装MySql的踩坑之旅
由于客户的CentOS服务器没有安装yum工具,只能通过下载tar.gz包安装mysql,于是跟着万能的百度开启了漫漫踩坑之旅: 1.下载mysql-5.6.33-linux-glibc2.5-x86 ...
- 我的微信小程序入门踩坑之旅
前言 更好的阅读体验请:我的微信小程序入门踩坑之旅 小程序出来也有一段日子了,刚出来时也留意了一下.不过赶上生病,加上公司里也有别的事,主要是自己犯懒,就一直没做.这星期一,赶紧趁着这股热乎劲,也不是 ...
- vue+ vue-router + webpack 踩坑之旅
说是踩坑之旅 其实是最近在思考一些问题 然后想实现方案的时候,就慢慢的查到这些方案 老司机可以忽略下面的内容了 1)起因 考虑到数据分离的问题 因为server是express搭的 自然少 ...
- Python踩坑之旅其一杀不死的Shell子进程
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...
- Python 踩坑之旅进程篇其三pgid是个什么鬼 (子进程\子孙进程无法kill 退出的解法)
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 Github: https: ...
- [代码修订版] Python 踩坑之旅 [进程篇其四] 踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 公 ...
- EasyTrader踩坑之旅总结
easytrader是用python写的可以调用主要券商完成自动化炒股的一个软件 ,但我用的是同花顺,在研究过程中,发现同花顺暂时调不通.后来搜索发现thstrade的源码作者说是easytrad ...
- vue踩坑之旅 -- computed watch
vue踩坑之旅 -- computed watch 经常在使用vue初始化组件时,会报一些莫名其妙的错误,或者,数据明明有数据,确还是拿不到,这是多么痛苦而又令人忍不住抓耳挠腮,捶胸顿足啊 技术点 v ...
随机推荐
- 关于第一次STM32连接电脑下载程序
安装了Keil(ARM)版本之后,不管是自己编程,还是配套的程序运行.我们都想把它下载到STM32芯片里面,在板子上运行.这里介绍几种方法. 1.用J-LINK下载调试. 这个工具,可以直接点击kei ...
- MongoDB备份和恢复
mongodump备份数据 该命令可以导出所有数据到指定目录中, 也能通过参数指定备份服务器 mongodump -h dbhost -d dbname -o dbdirectory dbhost: ...
- docker安装方法(常见安装出错问题汇总)
参考资料: 1. 开源中国 http://www.oschina.net/translate/nstalling-dockerio-on-centos-64-64-bit?cmp Docker 是一 ...
- [基础]PeopleSoft中的作业和调度作业集合定义
PeopleSoft进程调度器可以使一个或多个进程作为一个组.这个组在PeopleSoft中被称为作业(Job). PeopleSoft进程被定义为单个任务,程序或例程,例如cobol程序或AE程序或 ...
- Java的原始类型自动包装与解包机制
java5之后对原始数据类型如int.char.long等基本数据类型有自动打包成相应的复合类型Integer.Character.Long等的机制:也可以将复合类型自动转换为原始类型. 这取决于程序 ...
- C#使用Xamarin开发可移植移动应用(3.Xamarin.Views控件)附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. .NET ...
- jQuery.Gantt
使用jQuery.Gantt过程中,遇到的问题!
- angular学习(六)-- Filter
2.6 过滤器:Filter 内置过滤器 currency number date json uppercase lowercase orderBy limitTo filter 自定义过滤器
- JavaScript基础知识(二)
一.JavaScript事件详解 1.事件流:描述的是在页面中结束事件的顺序 事件传递有两种方式:冒泡与捕获. 事件传递定义了元素事件触发的顺序. 如果你将 <p> 元素插入到 <d ...
- 01-artDialog4.1.7常用整理
关闭弹出框的几种常见方法: 1,artDialog可以通过鼠标双击关闭对话框,esc关闭对话框等.为了在关闭对话框要执行某一方法,不能仅仅在弹框中的关闭按钮中写.这时提供了一个函数:close.无论在 ...