import { useState, useEffect } from 'react'; interface SafeAreaInsets { top: number; right: number; bottom: number; left: number; } export function useSafeArea() { const [safeAreaInsets, setSafeAreaInsets] = useState({ top: 0, right: 0, bottom: 0, left: 0 }); const [viewportHeight, setViewportHeight] = useState(0); useEffect(() => { const updateSafeArea = () => { // 获取 CSS 环境变量 const computedStyle = getComputedStyle(document.documentElement); const top = parseInt(computedStyle.getPropertyValue('--sat').replace('px', '')) || 0; const right = parseInt(computedStyle.getPropertyValue('--sar').replace('px', '')) || 0; const bottom = parseInt(computedStyle.getPropertyValue('--sab').replace('px', '')) || 0; const left = parseInt(computedStyle.getPropertyValue('--sal').replace('px', '')) || 0; setSafeAreaInsets({ top, right, bottom, left }); // 设置动态视口高度 const vh = window.innerHeight; setViewportHeight(vh); document.documentElement.style.setProperty('--vh', `${vh * 0.01}px`); }; updateSafeArea(); window.addEventListener('resize', updateSafeArea); window.addEventListener('orientationchange', updateSafeArea); // 延迟更新以处理移动端浏览器地址栏变化 const timeoutId = setTimeout(updateSafeArea, 500); return () => { window.removeEventListener('resize', updateSafeArea); window.removeEventListener('orientationchange', updateSafeArea); clearTimeout(timeoutId); }; }, []); return { safeAreaInsets, viewportHeight, /** 获取考虑安全区域的样式 */ getSafeAreaStyle: (includeBottom = true) => ({ paddingTop: `max(1rem, ${safeAreaInsets.top}px)`, paddingRight: `max(1rem, ${safeAreaInsets.right}px)`, paddingBottom: includeBottom ? `max(1rem, ${safeAreaInsets.bottom}px)` : undefined, paddingLeft: `max(1rem, ${safeAreaInsets.left}px)`, }) }; }