uniapp项目中H5页面解决ios中软键盘唤出导致页面偏移问题

问题出现


上图便是模块中发布帖子的页面,看上去没有什么坑可以踩,写完页面在电脑端和我自己的安卓手机上也都没什么问题,最后拿来苹果的测试机,打开页面便出现了如下问题

从两张图中可以看出,和安卓手机不同,唤起软键盘时底部的操作栏没有和软键盘一起被顶上来,仍处于页面最底端,需要向下滑动页面才可以看到,这和设计的初衷完全相悖。

问题原因

fiexd定位在ios唤起软键盘时失效

ios中唤起软键盘后会根据相应情况发生如下情况:

  • 当前内容高度小于屏幕高度时:上下滑动页面时候,发现之前fixed定位在顶部的元素会跟随页面滚动,变成了absolute定位的效果。
  • 当前内容高度大于屏幕高度时:之前fixed定位的元素不在原先的位置,下滑往上翻页面后,才会发现该元素出现在视图中。

ios在唤起软键盘时并不压缩webview高度


安卓手机中唤起软键盘时页面会压缩webview的高度,窗口会执行resize事件,但ios并不会。

解决思路

由于ios不压缩webview视图,我定位的元素仍在webview的底部,但与安卓不同的是此时webview的底部并不是软键盘上方。

所以如果我们可以获取到软键盘的高度,将元素重新定位便可以解决这个bug。

解决过程


项目是用uniapp开发的。

我的思路是通过innerHeight的变化来判断软键盘高度,但ios不压缩webview,所以这直接阻绝了我。就在我逐渐烦躁,几乎放弃,准备另寻思路的时候,偶然看见Element.scrollIntoView方法,执行此方法会滚动元素的父元素,直到该元素可视。

果断试一试,唤起软键盘时取消定位,ios效果如下:

可以看到 键盘弹出的时候,底部操作栏被推上来了,但问题也很明显,整个视图被上移了操作栏虽然出现在了软键盘上,但输入框却被挤到视图外,不过问题不大,我们的目的已经达到了,此时我们可以通过视图偏移量,来得到软键盘的高度。

通过Element.getBoundingClientRect方法,我们可以拿到视图的偏移量,该方法返回一个DOMRect对象,该对象提供有关元素大小及其相对于视图位置的信息。

获取到偏移量后为操作栏重新添加定位,但要注意重新定位底部操作栏后,上方编辑区域的高度也需要重新设置,不然会出现下面的情况,定位元素遮盖输入框。

在聚焦事件里根据视图偏移量为输入框设置高度,失去焦点时再还原,就解决元素错乱的问题。

最后附上结果:

贴上代码

<template>
  <view ref="posting" class="posting">
      <scroll-view 
           :style="{'height': scrollHeight}"
            class="scroll-view"
            :scroll-y="true">
        <view class="main">
            <u-input :height="200" :maxlength="500" v-model="value" @focus="focusIpt" @blur="blurIpt" placeholder="写下您的见解" type="textarea" />
        </view>
      </scroll-view>
      
      <view class="bottom" ref="bottom" :style="{'bottom': bottomVal + 'px', 'position': isFiexd ? 'absolute' : 'relative'}">
          <view class="edit-row">
             底部操作栏
          </view>
      </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
        bottomVal: 0,
        scrollHeight: 'calc(100vh - 196rpx)',
        isFiexd: true
    };
  },
  onLoad(e) {
  },
  methods: {
    blurIpt() {
        this.bottomVal = 0
        this.scrollHeight = 'calc(100vh - 196rpx)'
    },
    focusIpt() {
        //获取系统信息
        let info = uni.getSystemInfoSync()
        if(info.platform === 'ios') {
            this.isFiexd = false
            setTimeout(() => {
                this.$refs.bottom.$el.scrollIntoView()
                let viewInfo = this.$refs.posting.$el.getBoundingClientRect()
                //获取视图偏移量,重新定位操作栏
                this.bottomVal = Math.abs(parseFloat(viewInfo.top))
                //重置编辑区高度
                this.scrollHeight =  `calc(100vh - ${98 + this.bottomVal}px )`
                //还原偏移量
                scrollTo(0,0)
                this.isFiexd = true
            },500)
        }
    },
  }
};
</script>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

励志做个全栈开发的小男生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值