Figma 底部抽屉与拖拽手势高级原型实战(Bottom Sheet & On Drag):从多阶吸附断点(Collapsed/Half/Expanded)、嵌套滚动解耦到前端交付

2026 年 11 月 12 日

在当今移动端 App 设计中,底部抽屉(Bottom Sheet,亦称动作面板或滑动抽屉) 已成为无可争议的交互核心。从地图类应用(如 Apple Maps / 高德地图)的地点详情与路线面板,到音乐流媒体(如 Spotify / 网易云音乐)的正在播放条(Mini Player),再到社交电商的商品 SKU 选择与评论互动列表,底部抽屉凭借单手大拇指热区覆盖、渐进式信息暴露以及不中断主背景上下文的特性,彻底重塑了现代移动操作系统的体验基准。

然而,在日常 Figma 原型制作中,底部抽屉也是团队高频踩坑的“重灾区”:

  1. 只能点击不能拖拽:依赖传统 Open Overlay 遮罩弹窗,只能通过点击按钮“生硬”弹出或关闭,无法响应手指跟随拖拽(Drag)手势;
  2. 手势与列表滚动冲突:当用户在抽屉内滑动查看评论或菜单列表时,系统无法判断意图,误将内部列表滚动识别为收起抽屉,导致画面剧烈抖动;
  3. 缺乏吸附断点(Snap Points):现实产品普遍具备“收拢条(Mini)➔ 半屏(Half)➔ 全屏(Full)”的三阶吸附,但在 Figma 中往往画板连线混乱,动效机械僵硬;
  4. 交付前端参数脱节:研发接手后不知道手势速度阈值、阻尼系数与断点数组,最终线上还原度大打折扣。

本文将深入拆解底部抽屉的底层交互逻辑,指导你运用 Figma 的交互组件(Interactive Components)、On Drag 触发器、智能动画物理弹簧与嵌套滚动机制,构建真机质感的多阶吸附抽屉高保真原型。


1. 底部抽屉的核心交互模型与三阶吸附(Snap Points)架构 #

现代成熟商业产品的底部抽屉并非单一尺寸,而是根据用户任务的沉浸程度动态演变。

1.1 三阶断点模型(Three-Stop Snap Points) #

标准底部抽屉在移动端屏幕中通常定义 3 个物理吸附断点(Snap Points):

  • 折叠态(Peek / Collapsed State):高度通常为 64px ~ 80px。常驻在屏幕底部,仅暴露微型把手(Handle Bar)、简短标题或迷你控制条(如播放/暂停按钮),不遮挡主画板的核心视觉(如地图道路或视频画面);
  • 半屏态(Half / Mid Sheet):占据屏幕可视高度的 40% ~ 55%(约 360px ~ 440px)。展示主要操作卡片、摘要信息或高频快捷按钮,用户可在此状态下完成 80% 的日常浏览;
  • 全屏展开态(Full Expanded State):占据屏幕可视高度的 85% ~ 92%(顶部预留系统状态栏安全间距约 44px)。承载长文本详情、长评论列表或复杂筛选表单,允许内部发生垂直列表滚动。

1.2 原型技术方案对比矩阵 #

在 Figma 中实现抽屉原型存在多种思路,其适用场景与能力边界差异显著:

对比维度 方案 A:Open Overlay 遮罩弹窗 方案 B:交互组件状态机 (推荐) 方案 C:画板级 Smart Animate
手势支持 仅支持 Click / Tap 点击触发 原生支持 On Drag 拖拽跟随 支持 On Drag,但需要多画板连线
多阶吸附能力 仅支持固定高度单层弹窗 支持三阶(Collapsed/Half/Full)循环状态机 支持,但画板数量成倍递增
画板整洁度 高(仅需挂载一个覆盖层) 极高(单个组件封装全部状态) 极差(连线交错犹如蜘蛛网)
内部滚动支持 良好 优秀(通过图层嵌套解耦) 良好
组件复用性 差(只能作为独立 Frame 插入) 极高(作为 Master Component 跨项目复用) 极差(无法在其他文件无缝复制)
前端研发交接 无法体现手势吸附参数 清晰映射 Snap Points 状态流转 动效参数分散,标注繁杂

2. 实操步骤:从零构建支持 On Drag 拖拽的三态抽屉组件集 #

借助 Figma 的 Interactive Components(交互组件),我们可以将三阶吸附的所有状态机与手势逻辑完整内聚在一个组件集中。

2.1 步骤一:创建抽屉主容器与 Auto Layout 极值约束 #

  1. 新建一个 Frame,宽度设为移动端基准尺寸(如 390px,详见 主流设备尺寸速查表);
  2. 开启 Auto Layout(快捷键 Shift + A),设置为垂直排列(Direction: Vertical),内边距(Padding)设为:Top 12px、Left 16px、Right 16px、Bottom 34px(适配 iOS 底部 Home Indicator 区域);
  3. 容器顶部居中绘制一个拖拽把手(Handle Bar):宽 36px、高 4px、圆角 2px,填充浅灰色(如 #D1D5DB);
  4. 设置抽屉容器的上左与上右圆角为 20px(下左与下右圆角保持 0),开启背景色为纯白或深色主题卡片色;
  5. 在右侧面板配置外阴影(Drop Shadow):Y: -8px、Blur: 24px、Color: rgba(0, 0, 0, 0.08),赋予抽屉向上的物理悬浮层级。

2.2 步骤二:制作 Collapsed、Half、Expanded 三个变体 #

  1. 选中该容器,在顶部工具栏点击 Create Component(快捷键 Opt + Cmd + K 或 Ctrl + Alt + K),然后点击右侧面板的 + Add Variant;
  2. 将变体属性重命名为 State,分别制作 3 个变体:
    • 变体 1 (State=Collapsed):固定高度设为 80px,内部仅展示 Handle Bar 与一行简短摘要,超出部分隐藏(关闭多余内容图层或裁剪);
    • 变体 2 (State=Half):固定高度设为 400px,展现主体信息卡片与核心操作按钮组;
    • 变体 3 (State=Expanded):固定高度设为 720px,展现完整的长评论或详情列表。

    关键技巧:三态变体内部的所有共有图层(如 Handle Bar、Header 容器、Body 列表)必须保持完全一致的图层名称与层级拓扑结构,否则 Smart Animate 在变形过程中会发生淡入淡出(Cross-fade)而非流畅的几何高度形变。

2.3 步骤三:连接 On Drag 拖拽手势与 Spring 物理弹簧 #

进入右上角的 Prototype(原型) 面板,建立手势连线:

  1. 向上拖拽展开:
    • 选中 State=Collapsed 变体,将手势箭头拉至 State=Half 变体;
    • 触发器选择 On Drag(拖拽中);
    • 动画类型选择 Smart Animate,曲线选择 Spring(物理弹簧);
    • 弹簧参数建议:Stiffness: 250、Damping: 25、Mass: 1(呈现紧致自然的吸附回弹,无夸张余震);
    • 同样地,将 State=Half 变体的拖拽箭头连向 State=Expanded;
  2. 向下拖拽收起:
    • 选中 State=Expanded 变体的 Handle 区域,将手势箭头连回 State=Half,同样配置 On Drag 结合 Spring 动效;
    • 选中 State=Half 变体的 Handle 区域,将手势连回 State=Collapsed。

3. 深水区避坑:手势冲突与内部嵌套滚动解耦 #

构建商业级抽屉时,最棘手的问题莫过于手势冲突(Gesture Conflict):当抽屉内部承载长列表(如 50 条商品列表)时,用户本想向上滑动浏览第 20 条数据,却不慎触发了抽屉本身的手势,导致整个抽屉突然拉升或剧烈抖动。

3.1 冲突根源与事件捕获机制 #

在触摸设备与 Figma 原型引擎中,事件是沿渲染树向下传递或向上冒泡的。如果外层抽屉容器的整个区域都监听了 On Drag,只要手指接触屏幕并发生 Y 轴位移,该事件就会被外层容器霸道劫持,内部列表的滚动(Scroll)事件将永远无法被触发。

3.2 图层隔离解耦法则(Scrubber Isolation) #

解决该冲突的工业级法则在于热区隔离(Touch Target Segregation):

[BottomSheet Main Frame] (仅作为整体容器,不绑定全屏 Drag)
  ├── [Drag Handle Area] (高度 48px 的透明热区) ──▶ 仅在此图层绑定 On Drag
  ├── [Sheet Header (Title & Actions)] ─────────▶ 可配置点击关闭等操作
  └── [Content Scroll Container] (列表容器)
        └── [Long List Content] ────────────────▶ 仅在此容器设置 Vertical Scrolling
  1. 拖拽热区独立化:不要直接给外层最大的 Frame 挂载 On Drag。在顶部专门绘制一个高度为 48px 的透明热区容器(包含 Handle Bar 和标题),将变体间的 On Drag 连线全部改挂载到该热区图层上;
  2. 内容区域启用嵌套滚动:
    • 在抽屉内部放置内容长列表时,将其包裹在一个固定高度的子 Frame 中(如高度设为 Fill container);
    • 勾选右侧面板的 Clip content(裁剪超出内容);
    • 在 Prototype 面板中将 Overflow 属性设置为 Vertical scrolling(垂直滚动);
    • 这样,用户在手柄区拖拽即可触发抽屉高度吸附,而在下方内容区滑动则流畅触发列表垂直滚动,两者井水不犯河水。

3.3 半透明遮罩层(Backdrop Scrim)联动 #

为了增强全屏态下的沉浸聚焦感,抽屉拉起时主界面通常会蒙上一层黑色半透明遮罩:

  • 在 State=Collapsed 变体中,遮罩图层 Opacity: 0%,Visibility: Hidden;
  • 在 State=Half 变体中,遮罩图层 Opacity: 30%;
  • 在 State=Expanded 变体中,遮罩图层 Opacity: 60%;
  • 同时,为遮罩图层添加 On click ➔ Navigate to State=Collapsed 交互,实现移动端通用的“点击背景空白处关闭抽屉”原生行为。

4. Variables 驱动的高级抽屉状态与数据联动 #

如果你正在制作更复杂的交互流程(例如抽屉拉起时,底部导航栏需要下沉隐藏;或者抽屉内点击“购买”后修改全局购物车计数),单纯依靠变体连线已无法满足需求,此时需要引入 Figma Variables(变量与表达式)。

4.1 引入枚举/数值变量记录抽屉状态 #

  1. 新建变量集合 UI State,创建 Number 类型变量 sheet_position,初始值设为 0(0=Collapsed,1=Half,2=Expanded);
  2. 在变体的连线上,除了配置 Smart Animate 跳转,点击 + Add action 附加 Set variable:
    • 拖拽至 Half 时,执行 Set variable sheet_position = 1;
    • 拖拽至 Expanded 时,执行 Set variable sheet_position = 2;
    • 收起时,执行 Set variable sheet_position = 0。

4.2 驱动外层元素联动(Conditional Logic) #

通过监听 sheet_position 变量,主屏幕中的其他组件可自动做出响应:

  • 底部 TabBar 避让:给主页底部导航栏的位置绑定变量,当 sheet_position > 0 时,将其 Y 轴偏移下移 100px,自动为抽屉让出底部全量交互空间;
  • 状态回传与跨画板持久化:即使离开当前页面,再次返回时抽屉仍然能保持用户上次停留的展开深度。

5. Dev Mode 前端手势库交付与无障碍规范 #

在完成原型设计后,通过 Figma Dev Mode(开发模式) 交付研发是确保手势动效 100% 还原的最后关键一环。

5.1 前端工程化技术选型对照表 #

不同端上的手势引擎机制不同,在交付注解(Annotation)中清晰标明吸附数组与第三方成熟开源库映射,能为研发节省大量技术调研时间:

开发平台 / 框架 推荐主流开源手势库 核心配置参数映射对照
React Native @gorhom/bottom-sheet snapPoints={['10%', '50%', '90%']}、enablePanDownToClose={true}
Web / React / Vue vaul (Emil Kowalski 开源) <Drawer.Root snapPoints={[0.2, 0.5, 0.9]}>、弹性阻尼自动拟合 iOS
iOS (SwiftUI) 原生 .presentationDetents .presentationDetents([.fraction(0.15), .medium, .large])
Android (Compose) ModalBottomSheet rememberModalBottomSheetState(skipPartiallyExpanded = false)
Flutter DraggableScrollableSheet initialChildSize: 0.5, minChildSize: 0.1, maxChildSize: 0.9

5.2 交付动效物理参数标准 #

设计师应在 Dev Mode 中清晰标注物理曲线参数,避免工程师直接使用生硬的 linear 或 ease-in-out:

  • 吸附阈值(Velocity Threshold):手势向上滑动速度 $> 500\text{ px/s}$ 时,即使拖拽距离未过半,也强制直接吸附至下一阶断点;
  • 回弹阻尼(Damping Ratio):推荐交付阻尼比 $\zeta = 0.82 \sim 0.88$(属于轻度欠阻尼系统),在到位瞬间具备细腻自然的物理回弹质感;
  • 最小触摸热区:Handle Bar 周围的透明热区必须保证最小物理尺寸不低于 44x44pt,避免用户手指难以抓取。

5.3 无障碍(a11y)与键盘导航合规 #

  1. 焦点捕获(Focus Trapping):当抽屉处于 Expanded 全屏态时,研发必须设置焦点捕获,确保使用读屏器或外接键盘的用户按 Tab 键时焦点不会漏到下方的背景页面中;
  2. 硬件返回键映射:Android 物理返回键与键盘 Esc 键必须映射为第一优先级收起抽屉;
  3. ARIA 语义交付:向研发标注抽屉外层容器应添加 role="dialog" 与 aria-modal="true" 属性,详见 无障碍合规落地实战。

若在原型预览过程中出现组件闪退或图层位移异常,可随时查阅 Figma 常见报错与疑难故障诊断手册 与 快捷键速查表 进行调试。通过手势热区隔离、三阶变体状态机与物理弹簧的深度调校,你便能在 Figma 中打造媲美原生 App 质感的工业级底部抽屉原型。

❓ 常见问题与答疑 (FAQ)

高频疑难解析与避坑指南
A

完全不需要。绝大多数核心功能在免费 Starter 计划中均可完整体验与实操练习,无需额外付费购买付费团队版。