ios 刘海屏 底部fixed定位 输入框键盘弹起之后底部有空余未正常恢复,最外层fixed,底部按钮也是fixed

import { useEffect } from 'react'

/**
 * 修复 iOS 键盘收起后页面不恢复的问题
 * 
 * 问题:iOS Safari 在键盘收起后,visualViewport.pageTop 不会自动归零,
 * 导致页面视觉上仍然被推上去
 * 
 * 解决方案:
 * 1. 监听 visualViewport.resize 事件
 * 2. 检测键盘弹起/收起(viewport 高度变化超过 100px)
 * 3. 键盘弹起时:滚动到顶部消除空白
 * 4. 键盘收起时:使用 scrollTo(0,1) -> scrollTo(0,0) 技巧强制 Safari 重新计算 viewport
 */
export const useIOSKeyboardFix = () => {
  useEffect(() => {
    if (typeof window === 'undefined' || !window.visualViewport) return

    let previousHeight = window.visualViewport.height

    const handleViewportResize = () => {
      const currentHeight = window.visualViewport!.height
      const heightDiff = currentHeight - previousHeight

      // 键盘弹起:高度减少超过 100px,滚动到顶部消除空白
      if (heightDiff < -100) {
        setTimeout(() => {
          window.scrollTo(0, 0)
          document.documentElement.scrollTop = 0
          document.body.scrollTop = 0
        }, 500)
      }
      // 键盘收起:高度增加超过 100px,重置 viewport 位置
      else if (heightDiff > 100) {
        requestAnimationFrame(() => {
          const viewportOffsetTop = window.visualViewport?.pageTop || 0
          
          if (viewportOffsetTop !== 0) {
            // 使用经典的 iOS scrollTo(0,1) -> scrollTo(0,0) 技巧强制 Safari 重新计算 viewport
            window.scrollTo(0, 1)
            
            requestAnimationFrame(() => {
              window.scrollTo(0, 0)
              document.documentElement.scrollTop = 0
              document.body.scrollTop = 0
            })
          } else {
            // viewport 正常,直接重置
            window.scrollTo(0, 0)
            document.documentElement.scrollTop = 0
            document.body.scrollTop = 0
          }
        })
      }

      previousHeight = currentHeight
    }

    window.visualViewport.addEventListener('resize', handleViewportResize)

    return () => {
      window.visualViewport?.removeEventListener('resize', handleViewportResize)
    }
  }, [])
}

  

posted @ 2025-10-27 16:14  红苹果学园  阅读(2)  评论(0)    收藏  举报