第2章:Material 3 设计语言——色彩系统、形状与字型、Material You 原理
说实话,刚开始接触 Material 3 的时候,我第一反应是:「这套色彩系统也太灵活了吧?」以前做 Material Design 2,调色板是固定的,Primary、Accent 写死。现在倒好,它直接拿你壁纸的颜色来生成主题——这就是 Material You 的核心。今天我们就顺着这根线,把色彩系统、形状字型、还有背后的自适应原理理清楚。
2.1 色彩系统:从「固定」到「动态」
Material 3 的色彩架构基于 色调调色板(Tonal Palette)。系统会从用户选择的壁纸中提取一个「源颜色(Source Color)」,然后自动生成 13 个色调色阶,每个色阶对应一个 调色板(Palette)。这些色阶再映射到具体的颜色角色上。
我遇到过不少团队,一上来就纠结「到底该用哪个色值」。实际上,真正重要的不是某个具体色值,而是 角色(Role) 和 对比度关系。
| 角色 | 用途 | 典型色调(深浅) |
|---|---|---|
| Primary | 主要组件、FAB | 调色板第 40 阶(浅色) / 第 80 阶(深色) |
| On Primary | Primary 上的文字 | 与 Primary 对比度 ≥ 4.5:1 |
| Secondary | 次要按钮、Slider | 调色板第 30 阶左右 |
| Tertiary | 强调性组件(如 Switch) | 另一组互补调色板 |
| Error | 错误状态、警示 | 固定红色调,#b3261e 等 |
| Neutral | 背景、Surface | 低饱和度灰阶 |
| Neutral Variant | Card 背景、分隔线 | 稍深于 Neutral |
你看,整个系统其实是一棵 递归树:源颜色 → 调色板 → 角色 → 具体组件。系统会自动计算对比度,你只需要告诉它「哪个角色给哪个组件」,剩下的交给算法。
我个人习惯在定义主题时,先用 MaterialColorUtilities 生成完整调色板,再按角色映射。千万别手动写死色值——一旦用户换了壁纸,整个主题就崩了。
2.2 形状与字型:风格一致性的「可配置标尺」
形状和字型是 Material 3 让我觉得最「舒服」的部分——它们被设计成了 可调的 Scale。说白了,就是一个等级系统,你只要选一个「形状风格」或「字型风格」,系统会自动推算出所有组件的对应参数。
2.2.1 形状系统
形状通过 CornerFamily(圆角、裁剪、弯曲)和 ShapeLevel(0、1、2、3)两层来控制。什么意思呢?拿一个 Button 举例:
- Level 0:直角,
corner-size: 0px - Level 1:小圆角,
4px - Level 2:中圆角,
8px - Level 3:完全圆角,
16px或更高
每个组件都有自己的默认等级。比如 FAB 默认用 Level 3,Card 用 Level 2。但你可以整体调整 ShapeTheme 来覆盖全局。
⚠️ 我曾经踩过一个坑:为了视觉统一,我把所有组件都改成一样的圆角大小。结果 Switch 的 thumb 和 Card 的圆角看起来很不协调。后来发现,官方建议不同组件保留不同等级,才能形成视觉层级。别盲目统一。
2.2.2 字型系统
字型系统也是类似的 Scale,包含 Display、Headline、Title、Body、Label 五大类,每类有 Large / Medium / Small 三种尺寸。区别在于行高、字重和字号。
| 样式 | 字重 | 行高(dp) | 典型字号(sp) |
|---|---|---|---|
| Display Large | 400 | 64 | 57 |
| Headline Medium | 500 | 44 | 32 |
| Title Small | 600 | 28 | 18 |
| Body Large | 400 | 24 | 16 |
| Label Small | 500 | 16 | 11 |
你想想看,如果让一个 Dialog 的标题用 Display Large,那就显得太小气了。Material 3 本身已经给了推荐映射:Dialog 的标题应该用 Headline Small 或 Title Large。跟着 Scale 走,少翻车。
2.3 Material You 原理:个性化不是玄学
Material You 不是一堆花哨的动画效果,它的本质是 动态主题生成 + 自适应组件。原理上就三步:
- 提取源颜色:从壁纸用 ML 聚类,选出最突出的颜色。
- 生成调色板:通过 HCT 色轮(色相+色度+亮度)计算 13 色调色板。
- 应用到角色:把调色板色阶分配给 Primary、Secondary 等。
注意,这个 HCT 色彩空间是 Google 自己搞的,比 HSL/HSV 更接近人眼感知。我刚开始不理解为什么不用旧的 Palette 工具,结果用 HCT 写了个 demo 试了下——嗯,壁纸是草地,生成的 Primary 确实是草绿色,而且浅色对比度刚好达标。比 HSL 准确太多。
// HCT 转换(简化)
hue = extractDominantHue(bitmap)
chroma = 48 // 固定饱和度
tone = 40 // Primary 标准亮度
primary = Hct.of(hue, chroma, tone)
// 自动生成调色板
tones = [10,20,30,40,50,60,70,80,90]
palette = tones.map(t => Hct.of(hue, chroma, t))
2.4 三个支柱的关系
色彩系统、形状字型、Material You 原理不是孤立的。它们共同决定了组件在不同的设备、不同的壁纸下,既能保持品牌一致性,又有足够的视觉层级。我把它画成一张图,你可以看到完整的输入输出链路。
这张图把上面讲的串联起来了。三个支柱各自独立,但最终都汇聚到「组件实例化」这一步。我写代码的时候,通常会先配好 MaterialTheme 的三个参数:colors、shapes、typography。只要这三个对象定义得干净,整个 App 的视觉一致性就至少有了 80%。
📌 小建议:做加密动画优化的时候,记得检查动画中用到的颜色是否来自 MaterialTheme.colors.onSurface 这类角色,而不是硬编码十六进制。不然你壁纸一换,动画里的颜色还是旧的,一眼就能看出不协调。
总结(但换个说法)
Material 3 的设计语言其实是在告诉你:别操心具体数值,去操心 映射关系。颜色用角色,形状和字体用 Scale,主题生成交给 HCT。你只要把「某个元素该用什么角色」定好,剩下的交给系统自动适应。
嗯,下一块内容我们就要开始聊加密动画里的优化细节了,但等你吃透了这套设计语言,那些动画的配色和形状才不会跑偏。