面试官:实现一个吸附在键盘上的输入框

公众号:程序员白特,欢迎一起交流学习~

来源:DAHUIAAAAAA,https://juejin.cn/post/7338335869709385780?searchId=20240424162151EE1DFC79521D9C9269CA

实现效果

话不多说,先上效果和 demo 地址:

demo 地址:https://codesandbox.io/p/devbox/keyboard-7fsqr8?file=%2Fsrc%2Fkeyboard.ts%3A54%2C24
体验地址:https://7fsqr8-5173.csb.app

实现原理

要实现一个吸附在键盘上的 input,可以分为以下步骤:

  1. 监听键盘高度的变化
  2. 获取「键盘顶部距离视口顶部的高度」
  3. 设置 input 的位置

第一步:监听监听键盘键盘高度的变化

要监听键盘高度的变化,我们得先看看在键盘展开或收起的时候,分别会触发哪些浏览器事件:

  • iOS 和部分 Android 浏览器

    展开:键盘展示时会依次触发 visualViewport resize -> focusin -> visualViewport scroll,部分情况下手动调用 input.focus 不触发 focusin

    收起:键盘收起时会依次触发 visualViewport resize -> focusout -> visualViewport scroll

  • 其他 Android 浏览器

    展开:键盘展示的时候会触发一段连续的 window resize,约过 200 毫秒稳定

    收起:键盘收起的时候会触发一段连续的 window resize,约过 200 毫秒稳定,但是部分手机上有些异常的 case:键盘收起时 viewport 会先变小,然后变大,最后再变小

总结两者来看,我们要监听键盘高度的变化,可以添加以下监听事件:

if (window.visualViewport) {
     
  window.visualViewport?.addEventListener("resize", listener);  
  window.visualViewport?.addEventListener("scroll", listener);  
} else {
     
  window.addEventListener("resize", listener);  
}  
  
window.addEventListener("focusin", listener);  
window.addEventListener("focusout", listener);  

===========================

📚 题外话: 获取键盘展开和收起状态

===========================

在实际业务中,获取键盘展开和收起的状态,同样很常见,要完成状态的判断,我们可以设定以下规则:

判断键盘展开:当 visualViewport resize/window.reszie、visualViewport scroll、focusin 任意一个事件触发时,如果高度减少,并且屏幕减少的高度(键盘高度)大于 200px 时,判断键盘为展开状态(由于 focusin 部分情况下不触发,所以还需要监听其他事件辅助判断键盘是否为展开状态)

判断键盘收起:当 visualViewport resize/window.reszie、visualViewport scroll、focusout 任意一个事件触发时,如果高度增加,并且屏幕减少的高度(键盘高度)小于 200px,判断键盘为收起状态

// 获取当前视口高度  
const height = window.visualViewport  
  ? window.visualViewport.height  
  : window.innerHeight;  
    
// 获取视口增量:视口高度 - 上次获取的视口高度  
const diffHeight = height - lastWinHeight;  
  
// 获取键盘高度:默认屏幕高度 - 当前视口高度  
const keyboardHeight = DEFAULT_HEIGHT - height;  
  
// 如果高度减少,且键盘高度大于 200,则视为键盘弹起  
if (diffHeight < 0 && keyboardHeight > 200) {
     
    onKeyboardShow();  
} else if (diff > 0) {
     
    onKeyboardHide();  
}  

同时,为了避免 “收起时 viewport 会先变小,然后变大,最后再变小” 这种

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值