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

前言

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

一、解决方法

/**
 * 监听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();
  };
}, []);

二、React Hook 实现形式

import { useEffect, useState } from 'react';

type MonitorSoftKeyboardAction = {
  /**
   * 软键盘是否收起
   */
  isDown?: boolean;
  /**
   * 软键盘是否弹起
   */
  isUp?: boolean;
};

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

// 默认差值范围 20
const DIFFERENCE_RANGE = 20;

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

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

  return { isDown, isUp: !isDown } as MonitorSoftKeyboardAction;
};

export default useMonitorSoftKeyboard;

三、解释

  1. 在 iOS 系统中,软键盘的弹起和收起确实不会触发 window.onresize 事件。这是一个已知的行为,与 Android 系统不同,Android 系统在软键盘弹起和收起时会触发 window.onresize 事件;
  2. 在 iOS 中软键盘弹起时,仅会引起 scrollTop 值改变,虽然我们可以通过输入框的获取焦点情况来做判断,但也只能在 iOS 中采用这个方案,因为在 Android 中存在主动收起键盘后,输入框并没有失焦,而 iOS 中键盘收起后就会失焦;
  3. 无论 iOS 还是 Android 在软键盘弹起的时候,会改变 body 的可视区域,也就是 clientHeight
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值