卷发哥哥 發表於 2023-7-28 10:24:21

iOS移动端软键盘弹起空白和滚动穿透问题解决方案

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>引言</li><li>键盘弹起空白</li><li>滚动穿透问题</li></ul></div><p class="maodian"></p><h2>引言</h2>
<p>在做h5移动端项目的时候,给用户一个十分友好的体验是很必要的。最近抽空整理了下移动端(iOS端)项目中经常碰到的两个问题</p>
<p class="maodian"></p><h2>键盘弹起空白</h2>
<p>在我们点击<code>input</code>等弹出手机键盘,在点击完成后经常会在底部出现跟键盘同大小的空白,但是当我们滚动下页面发现又好了,这个在iOS端可以说很常见的问题了(应该是布局定位造成的,具体原因没仔细研究),解决方法就是在结束输入的时候控制滚动条偏移下就好。</p>
<p>下面是相关代码:</p>
<div class="jb51code"><pre class="brush:cpp;">.inTouch {
-webkit-overflow-scrolling: auto;
}
.noTouch {
-webkit-overflow-scrolling: touch;
}</pre></div>
<div class="jb51code"><pre class="brush:js;">import Vue from 'vue'
Vue.directive('resetPage', {
inserted (el) {
    document.body.addEventListener('focusin', () =&gt; {
      if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
      // 软键盘收起的事件处理
      setTimeout(() =&gt; {
          document.getElementsByTagName('body').className = 'inTouch'
      }, 100)
      }
    })
    document.body.addEventListener('focusout', () =&gt; {
      if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
      // 软键盘收起的事件处理
      setTimeout(() =&gt; {
          const scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0
          window.scrollTo(0, Math.max(scrollHeight - 1, 0))
          document.getElementsByTagName('body').className = 'noTouch'
      }, 100)
      }
    })
}
})</pre></div>
<p>在iOS端,当元素获得焦点的时候,我们把<code>-webkit-overflow-scrolling</code>的值设为auto,防止滚动穿透。当元素失去焦点的时候,我们把值恢复为touch,这样页面的滚动效果不会丢失,同时我们控制滚动条偏移了<code>1像素</code>,解决软键盘弹起空白的问题。</p>
<p>关于我设置的<code>-webkit-overflow-scrolling</code>属性可多说两句:</p>
<div class="jb51code"><pre class="brush:cpp;">// -webkit-overflow-scrolling这个样式相信大家都很熟悉了,有auto、touch两个可选值
// auto:使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止。
// touch:使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。
// 为了增加滚动的流畅性,做iOS移动端适配的时候都会增加这个样式适配的
-webkit-overflow-scrolling: touch;</pre></div>
<p>查看兼容性的事后素我们发现只在iOS端可用,但是出现的问题也很多,我这里加上主要原因是当input失去焦点的时候,有的时候整个页面会卡顿住(这个问题在<code>webview</code>中碰到的),我发现加上这个之后会解决这个问题,就把这两个放到一起了,不需要的可以不加上这个相关的。</p>
<p>我用的是<code>mint-ui</code>开发的移动端,所以在输入框的时候就可以这样使用</p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;mt-field class="l-modal-body-input" v-reset-page :attr="{ maxlength: 15 }" v-model="name" label="姓名:"&gt;&lt;/mt-field&gt;</pre></div>
<p class="maodian"></p><h2>滚动穿透问题</h2>
<p>这个可以说也是很常见的问题了,在我们做弹框滚动,如地址或时间<code>picker</code>选择器的时候,我们在滚动选择时候,底部的页面也会跟着一起滚动,一定程度上影响了用户的体验。经查找研究,当我们弹框的时候移除body的<code>touchmove</code>事件,是可以解决这个问题的:</p>
<div class="jb51code"><pre class="brush:js;">// 锁定body滚动条--主要解决用户弹框滚动时的穿透
Vue.prototype.closeTouch = function () {
document.getElementsByTagName('body').addEventListener('touchmove', this.handler, {passive: false}) // 阻止默认事件
}
Vue.prototype.openTouch = function () {
document.getElementsByTagName('body').removeEventListener('touchmove', this.handler, {passive: false}) // 打开默认事件
}</pre></div>
<div class="jb51code"><pre class="brush:cpp;">handler: (e) =&gt; {
    e.preventDefault()
}</pre></div>
<p>当我们打开picker等弹框的时候,调用<code>this.closeTouch()</code>,锁定滚动,阻止默认事件。关闭弹框的时候调用<code>this.openTouch()</code>打开默认事件。过程虽然比较麻烦,但能实际解决问题!</p>
<p>以上是我做iOS移动项目时遇到的比较常见的问题,更多关于iOS软键盘弹起空白滚动穿透的资料请关注琼殿技术社区其它相关文章!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>解决IOS端微信H5页面软键盘弹起后页面下方留白的问题</li><li>总结IOS中隐藏软键盘的三种方式</li><li>iOS让软键盘消失的简单方法</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: iOS移动端软键盘弹起空白和滚动穿透问题解决方案