Skip to content

Elevation 设计规范

最后更新:2026-02-21 版本:v1.0 状态:✅ 强制执行

本文档定义 Reading Vocab Helper 项目的 Elevation(阴影层级)设计规范,包括标准值、各组件使用规范、暗色模式处理等。


📋 目录

  1. Elevation 标准层级
  2. 组件 Elevation 规范
  3. 暗色模式处理
  4. 决策树:如何选择 Elevation
  5. 代码示例
  6. 反模式总结

Elevation 标准层级

核心原则:使用 Material 3 标准层级值,确保视觉层次一致

Material 3 标准层级

层级数值用途视觉效果
Level 00dp平面元素、内嵌内容无阴影
Level 11dp悬浮卡片、轻量提升微弱阴影
Level 23dp菜单、下拉框、AppBar轻度阴影
Level 36dp底部弹窗、抽屉、FAB明显阴影
Level 48dp对话框较强阴影
Level 512dp模态层、全屏覆盖最强阴影

层级关系图

Level 5 (12dp) ─────────────────────────
                 全屏模态、侧边抽屉

Level 4 (8dp) ──────────────────────────
                 对话框、AlertDialog

Level 3 (6dp) ──────────────────────────
                 底部弹窗、FAB、抽屉

Level 2 (3dp) ──────────────────────────
                 菜单、PopupMenu、AppBar

Level 1 (1dp) ──────────────────────────
                 悬浮卡片、ListTile 悬浮

Level 0 (0dp) ──────────────────────────
                 平面内容、内嵌元素

组件 Elevation 规范

按组件类型

组件默认 Elevation悬浮/按下状态说明
Card0-1dp1-3dp默认 0,悬浮时 1
FilledButton0dp1dp(悬浮)默认平面
OutlinedButton0dp0dp始终平面
FloatingActionButton6dp8dp(按下)始终悬浮
AppBar0-3dp-滚动时 3dp
BottomNavigationBar3dp-固定 3dp
BottomSheet6dp-固定 6dp
AlertDialog8dp-固定 8dp
PopupMenu3dp-固定 3dp
Drawer6dp-固定 6dp
SnackBar6dp-固定 6dp

状态变化规则

交互状态对 Elevation 的影响:

默认状态 → 悬浮状态 → 按下状态
   0dp        +1dp       +3dp

暗色模式处理

核心原则:暗色模式使用 Surface Tint 替代阴影

Material 3 暗色模式策略

在暗色模式下,阴影不可见。Material 3 使用 Surface Tint(表面着色) 来表达层级:

层级Surface Tint 透明度视觉效果
Level 00%基础表面色
Level 15%轻微提升
Level 28%明显提升
Level 311%较高提升
Level 412%高提升
Level 514%最高提升

代码实现

dart
// Flutter 3.x 自动处理 Surface Tint
// 确保使用 Material 3 主题
ThemeData(
  useMaterial3: true,
  colorScheme: ColorScheme.fromSeed(
    seedColor: Colors.blue,
    brightness: Brightness.dark,  // 暗色模式
  ),
)

// Card 自动应用 Surface Tint
Card(
  elevation: 3,  // 暗色模式下自动使用 surfaceTintColor
  child: content,
)

// 手动设置 Surface Tint
Card(
  elevation: 3,
  surfaceTintColor: Theme.of(context).colorScheme.surfaceTint,
  child: content,
)

// 禁用 Surface Tint(如需纯色背景)
Card(
  elevation: 0,
  surfaceTintColor: Colors.transparent,
  child: content,
)

暗色模式设计建议

  1. 不要依赖阴影来区分层级

    • 暗色模式下阴影几乎不可见
    • 使用 Surface Tint 或边框来区分
  2. 使用 Material 3 组件

    • 自动处理 Surface Tint
    • 无需手动适配暗色模式
  3. 测试暗色模式

    • 确保层级关系在暗色模式下仍然清晰
    • 检查对话框、菜单等弹出组件

决策树:如何选择 Elevation

组件类型?
├─ 按钮
│  ├─ FilledButton → 0dp(默认),悬浮 1dp
│  ├─ OutlinedButton → 0dp(始终)
│  ├─ TextButton → 0dp(始终)
│  └─ FAB → 6dp(默认),按下 8dp

├─ 卡片/容器
│  ├─ Card(内嵌内容) → 0dp
│  ├─ Card(悬浮内容) → 1dp
│  └─ Card(可点击,重要) → 1-3dp

├─ 导航
│  ├─ AppBar(静止) → 0dp
│  ├─ AppBar(滚动) → 3dp
│  ├─ BottomNavigationBar → 3dp
│  └─ Drawer → 6dp

├─ 弹出/模态
│  ├─ PopupMenu → 3dp
│  ├─ BottomSheet → 6dp
│  ├─ AlertDialog → 8dp
│  └─ 全屏模态 → 12dp

└─ 反馈
   └─ SnackBar → 6dp

代码示例

Card 示例

dart
// Level 0:内嵌卡片(无阴影)
Card(
  elevation: 0,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(12),
    side: BorderSide(
      color: colorScheme.outline.withOpacity(0.12),
    ),
  ),
  child: content,
)

// Level 1:悬浮卡片
Card(
  elevation: 1,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(12),
  ),
  child: content,
)

// 可点击卡片(悬浮状态提升)
Card(
  elevation: isHovered ? 3 : 1,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(12),
  ),
  child: InkWell(
    onTap: onTap,
    borderRadius: BorderRadius.circular(12),
    child: content,
  ),
)

对话框示例

dart
// Material 3 标准对话框(自动 8dp)
AlertDialog(
  title: Text('标题'),
  content: Text('内容'),
  actions: [
    TextButton(onPressed: () {}, child: Text('取消')),
    FilledButton(onPressed: () {}, child: Text('确认')),
  ],
)

// 自定义 elevation
Dialog(
  elevation: 8,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(28),
  ),
  child: content,
)

FAB 示例

dart
// 标准 FAB(6dp)
FloatingActionButton(
  onPressed: onPressed,
  elevation: 6,
  highlightElevation: 8,  // 按下状态
  child: Icon(Icons.add),
)

// 小型 FAB
FloatingActionButton.small(
  onPressed: onPressed,
  elevation: 6,
  child: Icon(Icons.add),
)

// 扩展 FAB
FloatingActionButton.extended(
  onPressed: onPressed,
  elevation: 6,
  icon: Icon(Icons.add),
  label: Text('新建'),
)

AppBar 示例

dart
// 滚动时显示阴影
SliverAppBar(
  elevation: 0,  // 默认无阴影
  scrolledUnderElevation: 3,  // 滚动时 3dp
  title: Text('标题'),
)

// 普通 AppBar
AppBar(
  elevation: 0,  // Material 3 默认无阴影
  scrolledUnderElevation: 3,
  title: Text('标题'),
)

BottomSheet 示例

dart
// 模态底部弹窗(6dp)
showModalBottomSheet(
  context: context,
  elevation: 6,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
  ),
  builder: (context) => content,
)

// 持久底部弹窗
BottomSheet(
  elevation: 6,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(top: Radius.circular(28)),
  ),
  builder: (context) => content,
  onClosing: () {},
)

反模式总结

Elevation 值反模式

❌ 错误✅ 正确原因
elevation: 2elevation: 13非标准值
elevation: 4elevation: 36非标准值
elevation: 5elevation: 6非标准值
elevation: 10elevation: 812非标准值

层级关系反模式

❌ 错误✅ 正确原因
Card elevation > DialogCard < Dialog对话框应在卡片之上
AppBar elevation > BottomSheetAppBar < BottomSheet底部弹窗覆盖 AppBar
FAB elevation < CardFAB > CardFAB 应悬浮在内容之上

暗色模式反模式

❌ 错误✅ 正确原因
依赖阴影区分层级使用 Surface Tint暗色模式阴影不可见
手动设置暗色背景色使用 colorScheme.surface保持一致性
禁用 Surface Tint 后无边框添加边框区分保持层级可识别

快速参考表

标准 Elevation 值

层级组件
00dpFilledButton, OutlinedButton, 内嵌 Card
11dp悬浮 Card, FilledButton 悬浮
23dpAppBar 滚动, PopupMenu, BottomNavigationBar
36dpFAB, BottomSheet, Drawer, SnackBar
48dpAlertDialog, Dialog
512dp全屏模态

状态变化

组件默认悬浮按下
FilledButton010
Card0-1+1+2
FAB688
IconButton000

参考资料


维护者:Reading Vocab Helper Team 问题反馈:请在项目中提 Issue