Skip to content

图标尺寸规范

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

本文档定义 Reading Vocab Helper 项目的 图标尺寸规范,包括标准尺寸、各组件图标大小、颜色使用等。


📋 目录

  1. 标准图标尺寸
  2. 组件图标规范
  3. 图标颜色规范
  4. 决策树:如何选择图标大小
  5. 代码示例
  6. 反模式总结

标准图标尺寸

核心原则:使用 Material 3 标准图标尺寸

Material 3 标准尺寸

尺寸级别数值用途示例
超小16dp极小空间、微型指示器下拉箭头、状态点
18dp密集列表、辅助图标列表项尾部图标
按钮内20dp按钮内图标FilledButton.icon
标准24dp默认图标大小IconButton、AppBar
中等28dp略大图标重要操作图标
32dp导航图标BottomNavigationBar
超大36dp强调图标空状态、成功提示
特大40dp主要 CTA 图标FAB 图标
巨大48dp启动页、空状态主图标空白页插图中心

尺寸可视化

16dp ●     极小(下拉箭头)
18dp ●     小(密集列表)
20dp ●     按钮内
24dp ●●    标准(默认)
28dp ●●    中等
32dp ●●●   大(底部导航)
36dp ●●●   超大(强调)
40dp ●●●●  特大(FAB)
48dp ●●●●  巨大(空状态)

组件图标规范

按组件类型

组件图标大小说明
IconButton24dp(默认)可通过 iconSize 调整
AppBar actions24dp标准导航图标
AppBar leading24dp返回/菜单图标
FilledButton.icon18-20dp按钮内图标略小
OutlinedButton.icon18-20dp按钮内图标略小
TextButton.icon18-20dp按钮内图标略小
FloatingActionButton24dp(默认)FAB 自动居中
FloatingActionButton.large36dp大型 FAB
FloatingActionButton.small24dp小型 FAB
BottomNavigationBar24dp导航图标
NavigationRail24dp侧边导航
ListTile leading24dp列表项前导图标
ListTile trailing24dp列表项尾部图标
Chip18dp标签内图标
Badge16dp徽章内图标
SnackBar action24dp操作图标

特殊场景

场景图标大小说明
空状态插图48-64dp主图标
成功/失败反馈36-48dp强调图标
引导页插图48-64dp中心图标
设置项图标24dp与文字平齐
搜索框内图标20-24dp搜索/清除
输入框后缀20-24dp密码显示/清除

图标颜色规范

核心原则:使用 colorScheme 语义化颜色

颜色选择

图标类型推荐颜色示例
主要操作primaryFAB、主按钮图标
导航选中primary底部导航选中项
导航未选中onSurfaceVariant底部导航未选中项
列表项图标onSurfaceVariantListTile leading
辅助图标onSurfaceVariant说明、提示
错误图标error错误提示
成功图标tertiary 或 green成功反馈
禁用图标onSurface.withOpacity(0.38)禁用状态

自动颜色的组件

以下组件自动使用正确的颜色,无需手动设置:

组件自动颜色
IconButtononSurfaceVariant
ListTile.leadingonSurfaceVariant
AppBar.actionsonSurface
BottomNavigationBar自动选中/未选中
FilledButton.icononPrimary

决策树:如何选择图标大小

图标位置?
├─ 按钮内部
│  ├─ FilledButton.icon → 18-20dp
│  ├─ FAB → 24dp(标准)/ 36dp(大)
│  └─ IconButton → 24dp

├─ 导航
│  ├─ AppBar → 24dp
│  ├─ BottomNavigationBar → 24dp
│  └─ Drawer → 24dp

├─ 列表/表单
│  ├─ ListTile → 24dp
│  ├─ TextField 后缀 → 20-24dp
│  └─ Chip → 18dp

├─ 强调/反馈
│  ├─ 成功/失败图标 → 36-48dp
│  ├─ 空状态主图标 → 48-64dp
│  └─ 引导页图标 → 48-64dp

└─ 辅助
   ├─ Badge → 16dp
   ├─ 下拉箭头 → 16dp
   └─ 状态指示器 → 16dp

代码示例

标准图标

dart
// 默认 24dp 图标
Icon(Icons.home)

// 指定大小
Icon(Icons.home, size: 24)

// 带颜色
Icon(
  Icons.home,
  size: 24,
  color: colorScheme.onSurfaceVariant,
)

IconButton

dart
// 标准 IconButton(24dp 图标,48dp 触摸区域)
IconButton(
  icon: Icon(Icons.search),
  onPressed: onSearch,
)

// 自定义图标大小
IconButton(
  iconSize: 20,
  icon: Icon(Icons.close),
  onPressed: onClose,
)

// 填充样式
IconButton.filled(
  icon: Icon(Icons.add),
  onPressed: onAdd,
)

// 柔和填充样式
IconButton.filledTonal(
  icon: Icon(Icons.edit),
  onPressed: onEdit,
)

按钮内图标

dart
// FilledButton 带图标(图标自动 18dp)
FilledButton.icon(
  onPressed: onSave,
  icon: Icon(Icons.save),
  label: Text('保存'),
)

// OutlinedButton 带图标
OutlinedButton.icon(
  onPressed: onCancel,
  icon: Icon(Icons.close),
  label: Text('取消'),
)

// 自定义图标大小
FilledButton.icon(
  onPressed: onSave,
  icon: Icon(Icons.save, size: 20),  // 明确指定
  label: Text('保存'),
)

FAB

dart
// 标准 FAB(24dp 图标)
FloatingActionButton(
  onPressed: onAdd,
  child: Icon(Icons.add),
)

// 小型 FAB(24dp 图标)
FloatingActionButton.small(
  onPressed: onAdd,
  child: Icon(Icons.add),
)

// 大型 FAB(36dp 图标)
FloatingActionButton.large(
  onPressed: onAdd,
  child: Icon(Icons.add, size: 36),
)

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

底部导航

dart
// BottomNavigationBar(24dp 图标)
BottomNavigationBar(
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.book),
      label: '词汇',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.settings),
      label: '设置',
    ),
  ],
)

// NavigationBar (Material 3)
NavigationBar(
  destinations: [
    NavigationDestination(
      icon: Icon(Icons.home_outlined),
      selectedIcon: Icon(Icons.home),
      label: '首页',
    ),
  ],
)

列表项图标

dart
// ListTile 图标(自动 24dp)
ListTile(
  leading: Icon(Icons.person),
  title: Text('个人资料'),
  trailing: Icon(Icons.chevron_right),
)

// 自定义图标大小
ListTile(
  leading: Icon(Icons.person, size: 28),
  title: Text('个人资料'),
)

空状态图标

dart
// 空状态(大图标)
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(
      Icons.inbox_outlined,
      size: 64,
      color: colorScheme.onSurfaceVariant,
    ),
    SizedBox(height: 16),
    Text(
      '暂无数据',
      style: context.bodyLarge,
    ),
  ],
)

// 成功反馈
Icon(
  Icons.check_circle,
  size: 48,
  color: colorScheme.primary,
)

输入框图标

dart
// TextField 前缀图标
TextField(
  decoration: InputDecoration(
    prefixIcon: Icon(Icons.search, size: 24),
    hintText: '搜索...',
  ),
)

// TextField 后缀图标
TextField(
  decoration: InputDecoration(
    suffixIcon: IconButton(
      icon: Icon(Icons.clear, size: 20),
      onPressed: onClear,
    ),
  ),
)

反模式总结

尺寸反模式

❌ 错误✅ 正确原因
size: 22size: 2024非标准尺寸
size: 30size: 2832非标准尺寸
size: 25size: 2428非标准尺寸
size: 50size: 48非标准尺寸

颜色反模式

❌ 错误✅ 正确原因
Colors.greycolorScheme.onSurfaceVariant硬编码颜色
Colors.bluecolorScheme.primary硬编码颜色
Colors.redcolorScheme.error硬编码颜色
Colors.blackcolorScheme.onSurface硬编码颜色

使用反模式

❌ 错误✅ 正确原因
按钮内大图标 (32dp)按钮内小图标 (18-20dp)尺寸不协调
密集列表大图标密集列表小图标 (18dp)空间不足
导航小图标 (16dp)导航标准图标 (24dp)难以点击

🔴 图标容器反模式(P0 严重)

核心原则:禁止使用自定义 Container/BoxDecoration 包裹图标

Material 3 提供了专门的图标组件,不应该自定义容器来包裹图标。

❌ 错误做法✅ 正确做法场景
Container(decoration: BoxDecoration(...), child: Icon(...))IconButton.filledTonal(...)可点击的强调图标
Container(color: ..., child: Icon(...))IconButton.filled(...)可点击的主要图标
Container(shape: BoxShape.circle, child: Icon(...))CircleAvatar(child: Icon(...))装饰性圆形图标
自定义圆角矩形包裹图标直接使用 Icon(...)普通展示图标

错误示例

dart
// ❌ 错误:自定义容器包裹图标
Container(
  padding: const EdgeInsets.all(8),
  decoration: BoxDecoration(
    color: colorScheme.primary.withOpacity(0.1),
    shape: BoxShape.circle,
  ),
  child: Icon(Icons.check, color: colorScheme.primary),
)

正确示例

dart
// ✅ 正确:可点击图标按钮
IconButton.filledTonal(
  onPressed: onTap,
  icon: const Icon(Icons.check),
)

// ✅ 正确:装饰性圆形图标(不可点击)
CircleAvatar(
  backgroundColor: colorScheme.primaryContainer,
  child: Icon(Icons.check, color: colorScheme.onPrimaryContainer),
)

// ✅ 正确:普通展示图标
Icon(Icons.check, color: colorScheme.primary)

决策树:如何选择图标组件

图标是否可点击?
├─ 是 → 使用 IconButton 系列
│   ├─ 主要操作 → IconButton.filled
│   ├─ 次要操作 → IconButton.filledTonal
│   ├─ 低优先级 → IconButton.outlined
│   └─ 最低优先级 → IconButton(无背景)

└─ 否 → 装饰性图标
    ├─ 需要圆形背景 → CircleAvatar
    ├─ 需要徽章效果 → Badge
    └─ 普通展示 → Icon(无背景)

快速参考表

标准尺寸

尺寸使用场景
16dp微型指示器、下拉箭头、Badge
18dp密集列表、Chip
20dp按钮内图标、输入框后缀
24dp默认(IconButton、AppBar、ListTile)
28dp中等强调
32dp底部导航(较大设备)
36dp强调图标、大 FAB
40dp特大 CTA
48dp空状态、启动页

组件默认尺寸

组件默认图标大小
IconButton24dp
FilledButton.icon18dp
FAB24dp
FAB.large36dp
BottomNavigationBar24dp
ListTile24dp
Chip18dp
AppBar24dp

颜色映射

场景颜色
主要操作primary
导航选中primary
辅助图标onSurfaceVariant
错误图标error
禁用图标onSurface.withOpacity(0.38)

参考资料


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