IOS输入框聚焦会把内容区域顶起

文章描述了开发者遇到的问题,即在iOS设备上,H5聊天界面的输入框聚焦时,键盘弹起导致页面内容被顶上,解决办法是通过判断焦点变化调整空白元素高度以保持内容可见。作者还提供了相关的CSS和JavaScript代码示例以实现兼容性处理。
摘要由CSDN通过智能技术生成

前几天做了一个类似qq布局的h5的聊天界面,输入框固定在最底下。初始情况会有默认的两条聊天记录,但是当点击底部的输入框时,输入框聚焦,弹起键盘,然后整个界面就被顶上去了,然后那两条默认的聊天记录也被顶上去了,导致整个页面没内容了。

这张图片是初始页面
请添加图片描述
这张图片是点击输入框之后的样子,发现初始两条聊天内容被顶上去了
请添加图片描述

这里给出一个demo(如果样式有问题,请将浏览器的模拟器调到iphone 6/7/8)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
    content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no,viewport-fit=cover" />
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
      overflow: hidden;
      background-color: pink;
    }

    p {
      padding-bottom: 1.875rem;
    }


    .left {
      text-align: left;
    }

    .right {
      text-align: right;
      color: blue;
    }

    .chatContainer {
      height: 100%;
      padding-bottom: 30px;
      overflow: auto;
    }

    .inputBox {
      display: flex;
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0;
      height: 30px;
      z-index: 999;
    }

    input {
      flex: 1;
      margin-right: .5rem;
    }

    button {
      width: 6.25rem;
      height: 100%;
    }
  </style>
</head>

<body>
  <div class="chatContainer">
    <div class="flag"></div>
    <div class="chat">
      <p class="left">你好,我是XXX,一个机器人</p>
      <p class="left">请问您需要问什么</p>
    </div>
  </div>
  <div class="inputBox">
    <input type="text" />
    <button>发送</button>
  </div>

  <script>
    let oBtn = document.querySelector('button')
    let oChatContainer = document.querySelector('.chatContainer')
    let oChat = document.querySelector('.chat')
    let oInput = document.querySelector('input')

    oBtn.onmousedown = (e) => {
      e.preventDefault()
      let inputValue = oInput.value
      if (!inputValue) return
      let oDiv1 = document.createElement('p')
      let oDiv2 = document.createElement('p')
      oDiv1.className = 'right'
      oDiv1.innerText = inputValue
      oDiv2.className = 'left'
      oDiv2.innerText = '感谢您的回复!'
      oChat.appendChild(oDiv1)
      oChat.appendChild(oDiv2)
      let timer = setTimeout(() => {
        clearTimeout(timer)
        oDiv2.scrollIntoView({
          behavior: "smooth",
        })
      }, 100)
      oInput.value = ''
    }
  </script>
</body>

</html>

感觉这个好像并没有什么问题,安卓可以正常的显示,交互。但是IOS就是不行,并且我还设置了

  .inputBox {
      position: fixed;
      bottom: 0;
      z-index: 999;
    }

让我百思不得其解,,最后发现这是IOS手机的通病,没办法,只能进行hack了。

我的最终解决思路是,既然聚焦会定顶起内容区域,那么顶起来多少,我就用空白的元素占位多少高度,这样内容就显示出来了。当手指在屏幕滑动时,再把占位块高度变为0。如果内容区域足够高了,那么就不需要占位了,因为这个时候肯定有内容区域的元素露出来了。

最终的js代码如下

insetPlaceholder(oChatContainer, oInput)
function insetPlaceholder(containerEl, inputEl) {
  /**
   * 只有苹果手机会导致输入框聚焦顶底整个内容区域,
   * 所有这个函数只对IOS系统进行兼容处理
   */
  let isIos = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  if (!isIos) return

  /**
   * 这里这个是一个死的元素结构
   * 类似这样
   *  <div class="container">
        <div class="flag"></div>
        <div class="content"></div>
      </div>
    *  container是整体,flag是占位元素,根据情况切换高度
    *  content是实际的内容区域
    */
  let oFlag = containerEl.children[0]
  let oContent = containerEl.children[1]

  let firstFocusFlagElHeight = undefined
  // 能够显示出内容的最小高度
  let showInfoMinHeight = undefined

  const onInputFocus = () => {
    /**
     * 记录第一次聚焦的时候,container这个大盒子究竟被顶起来多少,把这个值记录为flag的高度
     * 
     * 如果oContent的高度大于700了,那就说明内容足够多了,不需要占位元素顶了
     */

    if (firstFocusFlagElHeight === undefined || (oContent.offsetHeight < showInfoMinHeight)) {
      let timer = setTimeout(() => {
        clearTimeout(timer)
        if (firstFocusFlagElHeight === undefined) {
          firstFocusFlagElHeight = Math.abs(oFlag.getBoundingClientRect().top)
          showInfoMinHeight = firstFocusFlagElHeight + oContent.offsetHeight
        }
        oFlag.style.height = firstFocusFlagElHeight + 'px'
      }, 3e2)
    }
  }

  oInput.addEventListener('focus', onInputFocus)
  /**
   * 监听这个事件主要是为了隐藏那个占位元素
   * 防止用户滑动界面把占位元素露出来
   * 并且很奇怪,如果不这样做,输入框会滚动!并且我已经设置了固定定位!
   */
  const onContainerElTouchstart = () => {
    oFlag.style.height = 0
    oInput.blur()
  }
  containerEl.addEventListener('touchstart', onContainerElTouchstart)
}

或者如果你的初始内容足够多,那你也不需要考虑这个问题

这里需要注意的是insetPlaceholder方法传入第一个参数是需要一个特定的html结构的,需要这样的结构

<div class="container">
   <div class="flag"></div>
   <div class="content"></div>
</div>

还有两个注意点这里说一下

oDiv2.scrollIntoView({
  behavior: "smooth",
})

这段代码用setTimout包裹了,不然动画无法执行(IOS不支持这个方法,只有安卓可以)

  1. 这里按钮的点击是监听的mousedown事件,并不是click,主要是为了阻止按钮点击触发输入框的失焦,会导致键盘收起,影响用户体验。
在微信小程序开发中,如果在iOS手机上遇到了键盘弹起时遮挡上面内容的问题,可以通过以下方法解决。 首先,我们需要获取键盘的高度。在小程序中,可以使用wx.getSystemInfoSync()方法来获取系统信息,其中包括键盘的高度。 接下来,我们需要监听键盘的弹起和隐藏事件。可以通过监听页面的focus和blur事件来实现。当input框被选中时(focus事件),我们可以将页面整体上移一个键盘高度的距离,以保证输入框不被键盘遮挡。当input框失去焦点时(blur事件),我们将页面恢复到原始位置。 具体实现时,可以在页面的onLoad生命周期函数中调用wx.getSystemInfoSync()方法获取系统信息,并存储键盘的高度。然后在页面的focus和blur事件中分别设置页面的上下边距,以达到上移和恢复的效果。 示例代码如下: ``` // 在页面的onLoad生命周期函数中获取系统信息 onLoad: function() { var that = this; wx.getSystemInfoSync({ success: function(res) { that.setData({ keyboardHeight: res.windowHeight * 0.75 // 假设键盘高度占屏幕高度的3/4 }); } }); }, // input获取焦点时的事件处理函数 onFocus: function() { this.setData({ marginTop: -this.data.keyboardHeight }); }, // input框失去焦点时的事件处理函数 onBlur: function() { this.setData({ marginTop: 0 }); } ``` 需要注意的是,根据不同手机型号和键盘设置的不同,键盘的高度可能有所差异,因此上述代码中获取到的键盘高度是一个近似值,可以根据实际情况进行调整。 以上是解决微信小程序开发中iOS手机键盘弹起时遮挡上面内容的一种方法,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值