移动端踩坑之旅-ios下fixed失效,软键盘等

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

  1、背景

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

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

  2、ios下fixed布局

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

1 <body>
2     <div class='top'></div>
3     <div class='main'></div>
4     <div class="fix-bottom"></div>
5 </body>复制代码

而后css就很少写了,浏览器上一看还挺想那么回事。而后在ios上就出现了点意外状况。就成了这个样子(但愿没有我厂的工友)程序员

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

  2.1 ios下fixed失效的缘由ajax

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

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

  2.2 如何解决bash

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

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

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

  二、不让页面滚动,而是让主体部分本身滚动

  若是fixed的失效,可是页面并无超过一屏的长度,那么不管absolut或者fixed也没什么差异。顺着这个思路咱们回顾一下上面的结构,彻底可让main直接滚着玩就好了。将吸底的元素和主题做为两大容器,主体部分,设置绝对定位,固定在屏幕中间,超出部分就自行滚动,吸底元素就能够本身玩了

大概就是下面这个样子:

1 <body>
2     <div class='warper'>
3         <div class='top'></div>
4         <div class='main'></div>
5     <div>
6     <div class="fix-bottom"></div>
7 </body>复制代码

对应样式以下:

1 .cont-warper{
 2     position: absolute;
 3     width: 100%;
 4     left: 0;
 5     right: 0;
 6     top: 0;
 7     bottom: 0;
 8     overflow-y: scroll;
 9     -webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */
10 }
11 .fix-bottom{
12     position:fixed;
13     bottom:0;
14     width: 100%;
15 }复制代码

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

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

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

  3、h5调用虚拟键盘

  解决了布局问题,下面就开始happy的写功能吧,开始以前,让咱们回头继续看下上面的视觉图,是否是感受少了点什么。咱们的提交button呢?通常来讲是这样:

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

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

  3.1 键盘提交事件

  通常来讲是这样作的,将input包括在form表单内,这样就能够监听submit事件了。若是有人问我是走的ajax不是form表单的话,请记得有个onSubmit事件能够来作一些你想作的事情。代码以下:

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

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

  一、submit事件能够监听到用户软键盘的回车键,对于ajax提交,这里须要咱们阻止下form的默认事件,避免form提交的刷新页面的行为

1  comment(postID, e) {
2         e.preventDefault()
3         // 阻止屡次提交
4         // 你的代码
5 
6     }复制代码

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

  3.2 其余区域唤起软键盘

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

  

移动端而言对于h5的input,focus和blur能够唤起和收起键盘,这样瓜熟蒂落的咱们可能这样作。给每一个回复绑定个事件,点击的时候让input获取焦点便可,代码以下

  

1 <div className="comment-resquetion" onClick={this.changeParent.bind(this, comment.comment)}>
 2 回复
 3 </div>
 4 //input获取焦点,并现实被回复人昵称
 5 changeparentComment(val) {
 6         let commentInput = document.querySelector('#commentInput')
 7         commentInput.focus()
 8         this.setState({
 9             parentComment: val
10         })
11     }复制代码

这样在android下面是能够的,在ios下面又遇到了问题,非input触发的事件是不能唤起键盘的,这样和window.open的限制差很少,只有用户主动的操做才会容许唤起键盘,因此这样是不能够的。

  针对这种状况,咱们能够投机取巧一下,既然必需要是input触发的操做,那么回复那里我直接用一个透明的input置于上方不就能够了。

  

1 <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: 0;
    z-index: 1000;
    left: 0.32rem;
    top: 0;
}复制代码

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

   3.3 关闭键盘

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

1 this.commentInput = document.querySelector('#commentInput')
2   setTimeout(() => {
3               this.commentInput.blur()
4               // 评论成功都置空
5              this.props.changeParent(null)
6    }, 500)复制代码

  到这里这个看起来很小的功能终于结束了,有必要作个总结以供本身及有须要的同窗作个参考。

参考文章:

efe.baidu.com/blog/mobile…

相关文章
相关标签/搜索