You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端Shadcn Drawer组件输入框被键盘遮挡问题求助

解决Shadcn Drawer内嵌表单移动端键盘遮挡问题

1. 修正视觉视口监听逻辑

之前的计算逻辑存在错误,正确的做法是让Drawer高度适配当前可视视口高度,同时调整底部定位避开键盘。修改后的代码如下:

import { useEffect, useRef } from 'react';
import { DrawerContent } from '@/components/ui/drawer';

export function YourDrawerComponent() {
  const drawerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleViewportChange = () => {
      if (!drawerRef.current || !window.visualViewport) return;
      
      // 可视视口高度(不含键盘)
      const viewportHeight = window.visualViewport.height;
      // 键盘高度 = 原始窗口高度 - 可视视口高度
      const keyboardHeight = window.innerHeight - viewportHeight;

      // 设置Drawer高度为可视视口高度,确保内容在键盘上方
      drawerRef.current.style.height = `${viewportHeight}px`;
      // 键盘弹出时,将Drawer底部设为键盘高度,避免被遮挡
      drawerRef.current.style.bottom = `${Math.max(keyboardHeight, 0)}px`;
    };

    const visualViewport = window.visualViewport;
    visualViewport?.addEventListener('resize', handleViewportChange);
    // 初始加载时执行一次,确保布局正确
    handleViewportChange();

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

  return (
    <DrawerContent ref={drawerRef} className="overflow-y-auto">
      {/* 你的表单内容 */}
    </DrawerContent>
  );
}

2. CSS层面优化增强适配

给DrawerContent添加滚动及布局属性,避免内容溢出或布局错乱:

.drawer-content-custom {
  /* 无键盘时默认占满屏幕高度 */
  height: 100vh;
  /* 内容超出时启用垂直滚动 */
  overflow-y: auto;
  /* 防止iOS弹性滚动影响布局 */
  overscroll-behavior-y: contain;
}

在组件中引用该类名:

<DrawerContent ref={drawerRef} className="drawer-content-custom">

3. 额外优化:输入框聚焦时自动滚动到可视区域

如果表单包含多个输入框,可在输入框聚焦时自动滚动到视图中心,进一步避免遮挡:

import { useRef } from 'react';

export function YourFormComponent() {
  const inputRefs = useRef<(HTMLInputElement | null)[]>([]);

  const handleInputFocus = (index: number) => {
    setTimeout(() => {
      inputRefs.current[index]?.scrollIntoView({
        behavior: 'smooth',
        block: 'center'
      });
    }, 100); // 延迟执行,确保键盘已完全弹出
  };

  return (
    <form>
      <input 
        ref={el => inputRefs.current[0] = el}
        onFocus={() => handleInputFocus(0)}
        placeholder="输入框1"
      />
      <input 
        ref={el => inputRefs.current[1] = el}
        onFocus={() => handleInputFocus(1)}
        placeholder="输入框2"
      />
      {/* 更多输入框 */}
    </form>
  );
}

原代码失效原因

  • 错误使用visualViewportHeight - drawerHeight设置Drawer高度,导致Drawer被压缩至不合理尺寸
  • diffFromInitial计算逻辑冗余,实际等同于visualViewportHeight,造成底部定位错误
  • 未在初始加载时执行监听函数,Drawer初始布局不符合预期

内容的提问来源于stack exchange,提问作者Kaze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 06:02:47