H5移动端监听软键盘弹起、收起

前言

H5 有时底部按钮是固定定位,当页面上面需要用到输入内容时,会弹起软键盘,然后把底部固定的按钮也弹起来了,我们希望弹起软键盘时,底部的固定定位按钮隐藏,这里就需要对移动端软键盘弹起收起进行监听。

解决方法

/**
 * 监听H5软键盘弹起
 * @param callback 
 * @param differenceRange 
 * @returns 
 */
export const monitorSoftKeyboard: Function = (
    callback: ({ isUp, isDown }: { isUp?: boolean; isDown?: boolean }) => void, // 监听软键盘弹起或降落的回调
    differenceRange: number = 20 // 默认差值范围 20
) => {
  const originalHeight =
    document.documentElement.clientHeight || document.body.clientHeight;
  const onResize = () => {
    // 键盘弹起与隐藏都会引起窗口的高度发生变化,这是主要的监听依据;
    const resizeHeight =
      document.documentElement.clientHeight || document.body.clientHeight;
    // 兼容IOS系统的某些大屏手机【从未弹起的软键盘clientHeight】和【弹起再收起后的clientHeight】不完全相同,存在差值;
    // 如果差值小于默认差值范围,即20,则认为软键盘已收起。
    if (Math.abs(originalHeight - resizeHeight) <= differenceRange) {
      // 软键盘收起
      callback({ isUp: false, isDown: true });
    } else {
      // 软键盘弹起
      callback({ isUp: true, isDown: false });
    }
  };
  window.addEventListener("resize", onResize);
  return () => window.removeEventListener("resize", onResize);
};

// ------------------------------page.tsx-------------------------------

const [showBottom, setShowBottom] = useState<boolean>(true);

useEffect(() => {
  const remove = monitorSoftKeyboard(({ isDown }) => {
    if (isDown) {
      setShowBottom(true);
    } else {
      setShowBottom(false);
    }
  });

  return () => {
    remove();
  };
}, []);

Hooks 实现形式

import { useEffect, useState } from 'react';

type CallbackParams = {
  isDown?: boolean;
  isUp?: boolean;
};

type Props = {
  callback?: (params?: CallbackParams) => void; // 监听软键盘弹起或降落的回调
  differenceRange?: number; // 差值范围,默认 20,兼容IOS可用
};

/**
 * 监听H5软键盘弹起
 * @param props
 * @returns
 */
const useMonitorSoftKeyboard = (props?: Props) => {
  const [isSoftKeyboardDown, setIsSoftKeyboardDown] = useState<boolean>(true);

  useEffect(() => {
    const originalHeight = document.documentElement.clientHeight || document.body.clientHeight;
    const monitorSoftKeyboard = () => {
      // 键盘弹起与隐藏都会引起窗口的高度发生变化,这是主要的监听依据;
      const resizeHeight = document.documentElement.clientHeight || document.body.clientHeight;
      // 默认差值范围 20
      const DIFFERENCE_RANGE = props?.differenceRange ?? 20;
      // 兼容IOS系统的某些大屏手机【从未弹起的软键盘clientHeight】和【弹起再收起后的clientHeight】不完全相同,存在差值;
      // 如果差值小于默认差值范围,即20,则认为软键盘已收起。
      if (Math.abs(originalHeight - resizeHeight) < DIFFERENCE_RANGE) {
        // 软键盘收起
        setIsSoftKeyboardDown(true);
        props?.callback?.({ isDown: true, isUp: false });
      } else {
        // 软键盘弹起
        setIsSoftKeyboardDown(false);
        props?.callback?.({ isDown: false, isUp: true });
      }
    };
    window.addEventListener('resize', monitorSoftKeyboard);
    return () => {
      window.removeEventListener('resize', monitorSoftKeyboard);
    };
  }, [props]);

  return { isSoftKeyboardDown, isSoftKeyboardUp: !isSoftKeyboardDown } as {
    isSoftKeyboardDown: boolean;
    isSoftKeyboardUp: boolean;
  };
};

export default useMonitorSoftKeyboard;

解释

  1. 在android中软键盘弹起或收起时,会改变window的高度,因此监听window的onresize事件;但是 ios 中软键盘的弹起收起并不触发 window.onresize 事件;
  2. 在 ios 中软键盘弹起时,仅会引起 scrollTop 值改变,但是我们可以通过输入框的获取焦点情况来做判断,但也只能在 ios 中采用这个方案,因为在 android 中存在主动收起键盘后,但输入框并没有失焦,而ios中键盘收起后就会失焦;
  3. 另外,focusin和focusout支持冒泡,对应focus和blur, 使用focusin和focusout的原因是focusin和focusout可以冒泡,focus和blur不会冒泡,这样就可以使用事件代理,处理多个输入框存在的情况。
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值