移动端软键盘

379 阅读1分钟

移动端软键盘


系统差异

在 Android 和 IOS 中呼出软键盘会有不同的表现

-Android:呼出软键盘,webview页面高度被压缩(监听resieze事件会触发)

-IOS:呼出软键盘,webview整体上移,高度不变(监听resieze事件不触发)

问题一 滑动操作导致输入框被挡住

原因: 在正常情况下当 input 或 textarea 元素 focus 时输入框都应该固定在软键盘上方,但由于业务内有【滚动至底部】的需求,在滚动后输入框随着去到了手机底部

解决方案:在滚动至底部的函数中手动触发一下 scrollIntoView 方法,可以通过 document 的 activeElement 元素判断当前是否有 TEXTAREA 或者 INPUT 元素聚焦(tagName返回的标签名一定是全大写)

function scrollToBottom() {
  nextTick(() => {
    messageListRef.value?.scrollIntoView({
      behavior: 'smooth',
      block: 'end',
    });

    const tagName = document.activeElement?.tagName;
    if ((tagName === 'TEXTAREA' || tagName === 'INPUT') && isIOS) {
      setTimeout(() => {
        document.activeElement?.scrollIntoView();
      }, 50)
    }
  });
}

问题二 IOS聚焦时webview未被顶起

原因【未知】: ,在操作页面内其它元素后,点击输入框webview不会被顶起,但实际上已经成功聚焦,且输入文本后 IOS 还会自动触发 scrollIntoView 方法。

解决方案: 在输入框元素 focus 时手动触发一下 scrollIntoView 方法,此处定时器的延迟,关乎到软键盘呼出动画的时长,目前测试出最低 200ms 的延迟能成功触发(如果聚焦时正常顶起页面,scrollIntoView触发的滑动高度为0,所以并不会影响)

function handleFocus(event: FocusEvent) {
  const activeElement = document.activeElement;

  if (event.target === activeElement && isIOS) {
    setTimeout(() => {
      document.activeElement?.scrollIntoView();
    }, 350)
  }
}