Flutter 的默认颜色

Material 3 带来的最大改进之一是让几乎所有 widget 都从 ColorScheme 派生颜色。

但缺点也是很明显,哪个 widget 使用哪个颜色经常让我蒙逼,我经常搞不清楚某个widget的颜色配置。

比如说,你改变一个单独的颜色 primary,可能会影响按钮、开关、滑块、进度指示器、文本选择、复选框和许多其他组件。有些 widget 根据其状态(启用、禁用、选中、悬停、聚焦、按下)使用不同的颜色。

这篇文章是 Flutter Material widget 在没有任何自定义 ThemeData 覆盖的情况下,如何使用 ColorScheme 的完整参考。

ColorScheme 概览

Flutter 目前定义了以下颜色:

颜色标记 (Color Token) 用途说明 (Purpose) 用途说明
primary Primary accent color 主强调色 / 核心品牌色
onPrimary Content shown on primary 在主色上显示的文本或图标颜色
primaryContainer Filled containers 主色容器颜色(用于填充容器)
onPrimaryContainer Content on primaryContainer 在主色容器上显示的文本或图标颜色
secondary Secondary accent 次要强调色
onSecondary Content on secondary 在次要色上显示的文本或图标颜色
secondaryContainer Secondary containers 次要色容器颜色
onSecondaryContainer Content on secondaryContainer 在次要色容器上显示的文本或图标颜色
tertiary Third accent 第三强调色
onTertiary Content on tertiary 在第三色上显示的文本或图标颜色
tertiaryContainer Tertiary containers 第三色容器颜色
onTertiaryContainer Content on tertiaryContainer 在第三色容器上显示的文本或图标颜色
error Error color 错误状态颜色
onError Content on error 在错误色上显示的文本或图标颜色
errorContainer Error container 错误状态容器颜色
onErrorContainer Content on errorContainer 在错误状态容器上显示的文本或图标颜色
surface Default surfaces 默认常规表面颜色
onSurface Text/icons on surface 在常规表面上显示的文本或图标颜色
surfaceContainerLowest Lowest elevation 最低层级的表面容器颜色
surfaceContainerLow Low elevation 较低层级的表面容器颜色
surfaceContainer Medium elevation 中等层级的表面容器颜色
surfaceContainerHigh High elevation 较高层级的表面容器颜色
surfaceContainerHighest Highest elevation 最高层级的表面容器颜色
onSurfaceVariant Secondary text/icons 次要表面上的文本或图标颜色 / 次要文本色
outline Borders 边框/轮廓线颜色
outlineVariant Subtle borders 微弱/次要边框线颜色
shadow Shadows 阴影颜色
scrim Modal scrim 模态背景遮罩(半透明层)颜色
inverseSurface Inverse surfaces 反转表面颜色(用于与背景相反的暗/亮色组件,如 Snackbar)
onInverseSurface Content on inverse surface 在反转表面上显示的文本或图标颜色
inversePrimary Accent on inverse surfaces 反转表面上的强调色
surfaceTint Elevation tint 随层级(高度)变化的表面色调成分

各个 widget 的默认颜色

按钮

常规按钮使用以下颜色:

python 复制代码
# Create a simple translated markdown table as requested by the user ("直接翻译就行").
md_translation = """# Material Design 3 组件颜色映射表

| 组件 (Widget) | 背景 (Background) | 前景 (Foreground) |
| :--- | :--- | :--- |
| `FilledButton` (实心按钮) | `primary` (主色) | `onPrimary` (主色上内容色) |
| `FilledButton.tonal` (色调实心按钮) | `secondaryContainer` (次要颜色容器) | `onSecondaryContainer` (次要容器上内容色) |
| `ElevatedButton` (浮雕按钮) | `surfaceContainerLow` (较低层级表面容器) | `primary` (主色) |
| `OutlinedButton` (线框按钮) | `transparent` (透明) | `primary` (主色) |
| `TextButton` (文本按钮) | `transparent` (透明) | `primary` (主色) |
| `IconButton` (图标按钮) | `transparent` (透明) | `onSurfaceVariant` (次要表面内容色) |
| `IconButton.filled` (实心图标按钮) | `primary` (主色) | `onPrimary` (主色上内容色) |
| `IconButton.filledTonal` (色调实心图标按钮) | `secondaryContainer` (次要颜色容器) | `onSecondaryContainer` (次要容器上内容色) |
| `IconButton.outlined` (线框图标按钮) | `transparent` (透明) | `onSurfaceVariant` (次要表面内容色) |
"""

with open("material_design3_buttons_translated.md", "w", encoding="utf-8") as f:
    f.write(md_translation)
print("Done")
text 复制代码
Done

Material Design 3 组件颜色映射表

组件 (Widget) 背景 (Background) 前景 (Foreground)
FilledButton (实心按钮) primary (主色) onPrimary (主色上内容色)
FilledButton.tonal (色调实心按钮) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色)
ElevatedButton (浮雕按钮) surfaceContainerLow (较低层级表面容器) primary (主色)
OutlinedButton (线框按钮) transparent (透明) primary (主色)
TextButton (文本按钮) transparent (透明) primary (主色)
IconButton (图标按钮) transparent (透明) onSurfaceVariant (次要表面内容色)
IconButton.filled (实心图标按钮) primary (主色) onPrimary (主色上内容色)
IconButton.filledTonal (色调实心图标按钮) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色)
IconButton.outlined (线框图标按钮) transparent (透明) onSurfaceVariant (次要表面内容色)

浮动按钮(Floating button)

组件 (Widget) 背景 (Background) 前景 (Foreground)
FloatingActionButton (悬浮操作按钮) primaryContainer (主色容器) onPrimaryContainer (主色容器上内容色)
FAB.small (小号悬浮操作按钮) primaryContainer (主色容器) onPrimaryContainer (主色容器上内容色)
FAB.large (大号悬浮操作按钮) primaryContainer (主色容器) onPrimaryContainer (主色容器上内容色)
FAB.extended (扩展悬浮操作按钮) primaryContainer (主色容器) onPrimaryContainer (主色容器上内容色)

选择控件

组件 (Widget) 选中状态 (Selected) 未选中状态 (Unselected)
Checkbox (复选框) primary (主色) outline (边框色)
Radio (单选框) primary (主色) onSurfaceVariant (次要表面内容色)
Switch thumb (开关滑块) onPrimary (主色上内容色) outline (边框色)
Switch track (开关轨道) primary (主色) surfaceContainerHighest (最高层级表面容器)
Slider active (滑块激活部分) primary (主色) -
Slider inactive (滑块未激活部分) surfaceContainerHighest (最高层级表面容器) -
RangeSlider active (范围滑块激活部分) primary (主色) -
RangeSlider inactive (范围滑块未激活部分) surfaceContainerHighest (最高层级表面容器) -

进度指示器

组件 (Widget) 颜色标记 (Color) 中文翻译与说明
CircularProgressIndicator primary 圆形进度条(使用主色)
LinearProgressIndicator primary 条形/线性进度条(使用主色)

轨道颜色默认使用 surfaceContainer 颜色。

Chips

默认值根据 chip 类型和状态略有不同。下表显示了没有 ChipThemeData 覆盖时使用的颜色。

组件 (Widget) 未选中背景 (Background unselected) 未选中前景 (Foreground unselected) 选中背景 (Background selected) 选中前景 (Foreground selected)
AssistChip (辅助标签) surface (表面色) onSurface (表面内容色) --- (不可选中) (not selectable) ---
SuggestionChip (建议标签) surface (表面色) onSurface (表面内容色) --- (不可选中) (not selectable) ---
FilterChip (过滤标签) surface (表面色) onSurfaceVariant (次要表面内容色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色)
ChoiceChip (选择标签) surface (表面色) onSurfaceVariant (次要表面内容色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色)
InputChip (输入标签) surface (表面色) onSurface (表面内容色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色)

Chip 轮廓在显示轮廓时使用 outline(例如某些 FilterChipInputChip 变体)。

导航

组件 (Widget) 背景 (Background) 选中指示器 (Selected indicator) 选中图标/文本 (Selected icon/text) 未选中图标/文本 (Unselected icon/text)
NavigationBar (底部导航栏) surface (表面色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色) onSurfaceVariant (次要表面内容色)
NavigationRail (导航侧栏/侧边栏) surface (表面色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色) onSurfaceVariant (次要表面内容色)
NavigationDrawer (导航抽屉) surface (表面色) secondaryContainer (次要颜色容器) onSecondaryContainer (次要容器上内容色) onSurfaceVariant (次要表面内容色)
BottomNavigationBar (legacy) (传统底部导航栏) surface (表面色) --- primary (主色) onSurfaceVariant (次要表面内容色)
TabBar (标签栏) surface * (表面色) 指示器: primary (Indicator: 主色) primary (主色) onSurfaceVariant (次要表面内容色)
  • TabBar 本身不绘制背景。它继承其父元素的背景,通常是 AppBarsurface)或其他 Material

备注:

  • NavigationBarNavigationRailNavigationDrawer 都遵循相同的 Material 3 颜色模型:
  • 容器:surface
  • 选中指示器:secondaryContainer
  • 选中标签/图标:onSecondaryContainer
  • 未选中标签/图标:onSurfaceVariant
  • BottomNavigationBar 是 Material 2 组件。它不使用选择指示器;选中项简单地使用 primary 颜色。
  • TabBar 使用 primary 作为指示器和标签/图标的高亮色,而未选中标签使用 onSurfaceVariant
  • 禁用目标使用降低不透明度的前景色版本,而不是不同的 ColorScheme 条目。

应用栏(App bars)

组件 (Widget) 背景 (Background) 标题 (Title) 图标 (Icons) 操作按钮 (Actions)
AppBar (应用栏/常驻顶栏) surface (表面色) onSurface (表面内容色) onSurface (表面内容色) onSurface (表面内容色)
SliverAppBar (可滚动折叠顶栏) surface (表面色) onSurface (表面内容色) onSurface (表面内容色) onSurface (表面内容色)
BottomAppBar (底部应用栏) surfaceContainer (表面容器色) onSurface * (表面内容色) onSurface (表面内容色) onSurface (表面内容色)
  • BottomAppBar 通常用作 widget(如 IconButton)的容器,而不是显示标题。如果直接在里面放置文本,默认前景色是 onSurface

备注:

  • 在 Material 3 中,AppBar 不再默认使用 primaryonPrimary;它使用中性的 surface 颜色配 onSurface 内容。
  • 前导图标、操作图标和标题都默认使用 onSurface
  • 滚动到底部时状态会改变背景为提升的 surface(使用 Material elevation 系统),但前景色保持 onSurface
  • BottomAppBar 使用 surfaceContainer 来与主页面的 surface 略有区分,同时保持相同的 onSurface 前景色。

卡片

组件 (Widget) 背景 (Background) 默认文本 (Default text) 次要文本 (Secondary text) 图标 (Icons) 边框 (Border)
Card (常规卡片/高亮卡片) surfaceContainerLow (较低层级表面容器) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) ---
FilledCard (填充卡片) surfaceContainerHighest (最高层级表面容器) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) ---
OutlinedCard (线框/描边卡片) surface (表面色) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) outlineVariant (次要边框线颜色)

备注:

  • CardFilledCardOutlinedCard 只定义容器颜色(对于 OutlinedCard,还有边框颜色)。
  • 文本和图标从周围主题继承颜色。标准 Text widget 使用 onSurface,而次要文本(例如 TextTheme.bodySmall)和许多 Material 图标使用 onSurfaceVariant
  • 卡片本身不覆盖前景色,不像 FilledButtonAlertDialog 等组件。这使它们适合作为可以包含任意内容的中性 surface。

边框:outlineVariant

对话框

组件 (Widget) 背景 (Background) 标题 (Title) 内容 (Content) 图标 (Icons) 操作按钮 (Actions)
AlertDialog (警告对话框) surfaceContainerHigh (较高层级表面容器) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) secondary (次要颜色) primary (主色)
Dialog (基础对话框) surfaceContainerHigh (较高层级表面容器) onSurface * (表面内容色) onSurface * (表面内容色) onSurface * (表面内容色) primary (主色)
SimpleDialog (简单对话框) surfaceContainerHigh (较高层级表面容器) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) secondary (次要颜色) ---
DatePickerDialog (日期选择对话框) surfaceContainerHigh (较高层级表面容器) onSurface (表面内容色) onSurface (表面内容色) primary (主色) primary (主色)
TimePickerDialog (时间选择对话框) surfaceContainerHigh (较高层级表面容器) onSurface (表面内容色) onSurface (表面内容色) primary (主色) primary (主色)
  • Dialog 只是一个容器。它本身不定义标题、内容或图标颜色------这些取决于你放在里面的 widget。如果你使用标准的 TextIconTextButton widget,它们分别解析为 onSurfaceonSurfaceprimary

备注:

  • AlertDialogSimpleDialog 有意使用 onSurfaceVariant 作为正文文本,使其比标题强调度更低。
  • 对话框图标(AlertDialog.iconSimpleDialog)默认使用 secondary,符合 Material 3 规范。
  • 对话框操作按钮通常是 TextButton,所以它们的前景色是 primary
  • 所有对话框在 Material 3 中默认使用 surfaceContainerHigh 作为容器颜色。

菜单

组件 (Widget) 背景 (Background) 文本 (Text) 图标 (Icons) 选中/聚焦项 (Selected/Focused item)
MenuBar (菜单栏) surfaceContainer (中等层级表面容器) onSurface (表面内容色) onSurface (表面内容色) 背景: secondaryContainer 前景: onSecondaryContainer
MenuAnchor (菜单锚点/菜单面板) surfaceContainer (中等层级表面容器) onSurface (表面内容色) onSurface (表面内容色) 背景: secondaryContainer 前景: onSecondaryContainer
PopupMenuButton (弹出菜单按钮) surfaceContainer (中等层级表面容器) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) 背景: secondaryContainer 前景: onSecondaryContainer
DropdownMenu (下拉菜单) 菜单背景: surfaceContainer 文本框(填充时): surfaceContainerHighest onSurface (表面内容色) onSurfaceVariant (次要表面内容色) 背景: secondaryContainer 前景: onSecondaryContainer

备注:

  • 菜单 surface 本身使用 surfaceContainer
  • 菜单项标签默认使用 onSurface
  • 前导和尾随图标通常使用 onSurfaceVariantMenuBar 除外,它们继承 onSurface)。
  • 高亮(悬停、聚焦或键盘选中)的菜单项使用 secondaryContaineronSecondaryContainer,与 Material 3 其他选择模式一致。
  • 禁用的菜单项使用降低不透明度的正常前景色版本,而不是不同的 ColorScheme 颜色。

这是 Material 3 非常一致的一个领域:几乎每个菜单组件都使用 surfaceContainer 作为弹出 surface,用 secondaryContainer 来表示当前高亮项。

列表

Material Design 3 列表项组件 (ListTile Widget) 颜色映射表

组件 (Widget) 背景 (Background) 标题 (Title) 副标题 (Subtitle) 前置/后置组件 (Leading/Trailing) 选中状态 (Selected)
ListTile (列表项) surface (表面色) onSurface (表面内容色) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) 标题与前置/后置组件变为主色: Title & leading/trailing → primary

补充说明:

  • 即使 selectedtrue,背景仍然是 surface,除非你显式设置 selectedTileColor
  • selected: true 时,标题和前导/尾随图标变为 primary
  • 副标题不会 变为 primary;它保持 onSurfaceVariant
  • 禁用的列表项降低这些颜色的不透明度,而不是切换到不同的 ColorScheme 条目。
  • 如果提供了 textColoriconColor,它们会覆盖这些默认值。

这是少数几个不同文本元素有意默认使用不同语义颜色的 Material widget 之一。

输入字段

TextFieldTextFormField

输入框构成元素 (Element) 默认状态 (Default) 聚焦状态 (Focused) 错误状态 (Error)
填充型背景 (Background - filled) surfaceContainerHighest (最高层级表面容器) surfaceContainerHighest (最高层级表面容器) surfaceContainerHighest (最高层级表面容器)
线框型背景 (Background - outlined) transparent (透明) transparent (透明) transparent (透明)
输入文本 (Input text) onSurface (表面内容色) onSurface (表面内容色) onSurface (表面内容色)
光标 (Cursor) primary (主色) primary (主色) error (错误提示色)
标签文本 (Label) onSurfaceVariant (次要表面内容色) primary (主色) error (错误提示色)
提示文本 (Hint) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色)
辅助文本 (Helper text) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) ---
错误文本 (Error text) --- --- error (错误提示色)
边框线 (Border) outline (边框/轮廓线颜色) primary (主色) error (错误提示色)
前缀/后缀图标 (Prefix/Suffix icons) onSurfaceVariant (次要表面内容色) onSurfaceVariant (次要表面内容色) error (错误提示色)

备注:

  • 表格假设使用 Material 3 提供的默认 InputDecorationTheme
  • 填充和轮廓字段只在容器颜色上不同;大多数前景色是相同的。
  • 输入文本在所有状态下保持 onSurface
  • 当字段进入错误状态时,光标、标签、边框和前缀/后缀图标都变为 error
  • 占位符(hintText)和辅助文本无论是否聚焦都继续使用 onSurfaceVariant

文本选择

元素 (Element) 颜色权标 (Color)
Cursor (光标) primary (主色)
Selection (选中的文本区域) primary (with reduced opacity) (主色,降低不透明度/半透明)
Selection handles (文本选择控制柄/水滴光标) primary (主色)

SnackBar

属性 (Property) 颜色权标 (Color)
Background (背景) inverseSurface (反转表面色)
Text (文本) onInverseSurface (反转表面内容色)
Action (操作按钮) inversePrimary (反转表面上的强调色)

Tooltips

属性 (Property) 颜色权标 (Color)
Background (背景) inverseSurface (反转表面色)
Text (文本) onInverseSurface (反转表面内容色)

Badges

属性 (Property) 颜色权标 (Color)
Background (背景) error (错误状态色)
Text (文本) onError (在错误色上显示的文本颜色)
Material 3 有意对 badge 使用 error/onError,但这是否合适取决于 badge 的含义。

分隔线

组件 (Widget) 颜色权标 (Color)
Divider (水平分隔线) outlineVariant (微弱/次要边框线颜色)
VerticalDivider (垂直分隔线) outlineVariant (微弱/次要边框线颜色)

滚动条

组件 (Widget) 颜色权标 (Color)
Scrollbar thumb (滚动条滑块) onSurfaceVariant (次要表面内容色)

Material

一个普通的 Material widget 背景默认为 surface

根据 elevation,它可能使用以下之一:

  • surfaceContainerLowest
  • surfaceContainerLow
  • surfaceContainer
  • surfaceContainerHigh
  • surfaceContainerHighest

完整的 ColorScheme 使用

这一节回答反向问题:

"如果我改变一个颜色,哪些 widget 会改变?"

颜色权标 (ColorScheme color) 被哪些组件/元素使用 (Used by)
primary FilledButtonTextButtonOutlinedButtonCheckboxRadioSliderProgressIndicatorTextField 聚焦状态、TabBarBottomNavigationBar、光标 (cursor)、选择区域 (selection)、Switch 轨道
onPrimary FilledButton 文本、IconButton.filledSwitch 滑块键
primaryContainer FloatingActionButton (悬浮操作按钮)
onPrimaryContainer FloatingActionButton 的图标/文本
secondaryContainer FilledButton.tonalNavigationBar 指示器、NavigationRail 指示器、NavigationDrawer 指示器、选中的 Chips (标签页)
onSecondaryContainer 音调填充按钮 (Tonal button) 文本、选中的 chip 文本
error 错误提示文本、错误状态边框、徽章 (Badge)
onError 徽章文本 (Badge text)
surface AppBarMaterial 组件、ListTile
surfaceContainerLow ElevatedButton (浮雕按钮)、Card (卡片)
surfaceContainer BottomAppBar (底部应用栏)、menus (各种菜单)
surfaceContainerHigh Dialogs (各种对话框)
surfaceContainerHighest 填充型 TextField (输入框) 背景、未激活的 slider (滑块) 轨道
onSurface 默认文本/图标
onSurfaceVariant 次要文本、提示文本 (hints)、图标、RadioScrollbar (滚动条)
outline 线框型 TextFieldCheckbox 边框
outlineVariant Divider (分隔线)、Card 边框

最后的想法

Flutter 的 Material 3 实现非常一致。大多数 widget 不再定义自己的颜色,而是从 ColorScheme 派生,允许通过仅更改少量值来重新主题整个应用。

然而映射并不总是显而易见的。将这样的参考放在手边,在追踪为什么改变一个颜色会影响看似不相关的 widget 时,可以节省大量时间。

相关推荐
IT_陈寒1 小时前
Vite打包时踩的坑:静态资源为啥突然404了?
前端·人工智能·后端
神奇的程序员10 小时前
我的软件冲进苹果商店下载榜前 50 了
前端
阳光是sunny11 小时前
别再被 worktree 绕晕了!AI 编程时代你必须掌握的 Git 隔离神器
前端·人工智能·后端
万少12 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
尘世中一位迷途小书童14 小时前
用 Cesium 撸了一个森林火情监控大屏,弧线、粒子、发光效果都齐了
前端·javascript
IT_陈寒15 小时前
垃圾回收器选错了,我的Java服务内存炸了
前端·人工智能·后端
月光下的丝瓜16 小时前
Flutter 国内安装指南
前端·flutter
玄星啊16 小时前
AI 编程的第 30 天,我怀念古法 Coding 了
前端·ai编程
Jolyne_16 小时前
Angular基础速通
前端·angular.js