主题与动态取色机制
别名: 动态取色 · 颜色角色 · 色调盘 · tonal palette
概念解释
Material 里组件不涂十六进制,只声明自己用的颜色角色(color role):主色、次色、第三色、错误色、表面、写在表面上的字。动态取色(dynamic color)从一张种子色——壁纸、品牌种子、或系统当前取色——生成一条色调盘(tonal palette),再把盘上的不同明度填进这些角色。同一颗按钮在两台设备上可以是两个完全不同的色值,但角色没变:它仍然是「主色容器上的主色字」。
它回答的是「颜色从哪来、怎么随设备变还不改组件结构」,不是「换一套皮肤但骨架不动」那种换皮流程。硬把品牌专色写进按钮,等于绕过角色层,动态取色一开,这块就会和其他表面对不上,对比也可能掉到无法阅读。
机制
角色把「干什么」和「涂成什么」拆开。生成器先把种子展开成一组有序明度,再按浅色/深色主题把明度映射到角色:浅色主题里表面用高明度、字用低明度;深色主题对调。组件只读角色,所以主题切换和壁纸换色都不要求改组件代码——改的是映射表。动态取色能在设备间看起来「还是这个应用」,是因为角色关系(谁衬谁、谁更强调)被保住了;保住的不是某一颗色值。
错误色、描边、禁用叠层也是角色,不是临时调的红。若警告和主色抢同一个角色,动态取色之后两者可能变得几乎同色,语义通道就塌了。对比是在角色对上计算的(表面对「写在表面上的字」),不是在设计稿的某两个色块上计算的;只盯着稿上的对比,过不了用户壁纸那一关。
边界
医疗警示、财务亏盈、地图图例这类已经占用了颜色通道的内容,不能被动态取色改写,必须锁在不参与种子映射的角色或非主题色上。品牌有法律意义上的专色时,专色应停在内容层的标志和插画,而不是灌进所有主色角色,否则壁纸一变标志色也会漂。低视力用户若在系统里强制了高对比方案,动态取色必须让路,不能把种子色的低对比组合再铺一层。没有壁纸、没有取色能力的设备(部分车机、电视、嵌入式屏)应退回静态角色表,而不是假装有一颗种子。打印和投影输出也没有「当前壁纸」,动态映射在那些表面上无意义。
怎么落地
- 组件和页面只引用颜色角色,禁止在控件上写死色值;品牌种子作为种子输入,而不是作为每个按钮的填充。
- 为错误、警告、成功准备独立角色,并在浅色、深色、以及至少两张反差极大的壁纸上检查角色对的对比。
- 把标志、插画、数据色从动态映射里豁免,声明哪些色不参与取色。
- 验证:换壁纸或切换浅色/深色后,主按钮、表面、错误提示和正文的角色关系仍可辨——强调的仍是主色、错误仍不同于主色、正文仍压在表面上。任何一块要靠设计师重涂才能看清的地方,都说明色值写进了组件而不是角色。再打开系统高对比,确认动态取色没有盖过它。