技术目标
- 会用
MaterialTheme.colorScheme、MaterialTheme.typography消费设计 token。 - 理解 浅色 / 深色 两套
ColorScheme的切换入口(本仓库:isSystemInDarkTheme())。 - 会把 语义色 (
primary、tertiary、primaryContainer...)与 组件默认值 对上号,并知道 业务层不直接写死 ARGB 的模块边界。

1. Theme 结构(Material3)
kotlin
MaterialTheme(
colorScheme = if (darkTheme) darkColorScheme() else lightColorScheme(),
typography = Typography(...),
shapes = Shapes(...),
) { /* content */ }
Composable 内用 MaterialTheme.colorScheme.primary 等取色;重组 时随上层 MaterialTheme 变化而更新子树。
本仓库入口 ComposeDemoTheme.kt:
darkTheme: Boolean = isSystemInDarkTheme():跟随系统深浅色。colorScheme:ComposeDemoLightColors/ComposeDemoDarkColors(lightColorScheme/darkColorScheme工厂)。typography:ComposeDemoTypography(见同模块Typography.kt)。
2. 自定义 Token(本仓库模式)
ComposeDemoTokens(与 ComposeDemoTheme 同文件)暴露 跨 feature 复用 的语义:
| Token | 映射 | 用途(文档语义) |
|---|---|---|
success |
colorScheme.tertiary |
成功态,不直接写绿 |
emphasisContainer |
primaryContainer |
强调块、提示条背景 |
onEmphasisContainer |
onPrimaryContainer |
其上文字色 |
使用方式:ComposeDemoTokens.emphasisContainer 等 仅在 @Composable 或 @ReadOnlyComposable 上下文中读取 ,内部仍走 MaterialTheme,换主题时一并更新。
边界 :业务/feature 模块依赖 :core:ui 的 Theme + Tokens ,避免在业务里散落 Color(0xFF...);DesignSystemSampleScreen.kt 下半段 硬编码色 仅作反例对照,勿复制到生产。
3. 形状与海拔(Elevation)
Material3 用 tonal elevation 、表面色调表达层次;Surface(tonalElevation = ...) 等与旧 M2「纯 shadow dp」心智不同。升级或混用 M2/M3 时以 官方迁移说明 为准。
本仓库样例屏以 色面 + Typography 为主,未演示复杂 elevation 矩阵;产品上应在设计稿中明确 卡片 / Dialog / BottomSheet 的层级 token。
4. 仓库路径小结
| 文件 | 作用 |
|---|---|
ComposeDemoTheme.kt |
MaterialTheme 包装 + ComposeDemoTokens |
Typography.kt |
字阶集中定义 |
DesignSystemSampleScreen.kt |
Token 行 vs 硬编码行截图对照 |
5. 风险清单
- 硬编码色值 :暗色模式与 对比度(WCAG) 易翻车;无障碍审核会卡。
- Typography 全表重写 :维护成本高;优先改
titleLarge/bodyLarge等少数 token,再局部TextStyle.merge。 - 三方 SDK 内部写死颜色 :只能 隔离层 包一层或换 SDK,不要假设能 100% Theme 化。
LocalContentColor/LocalTextStyle未随父级更新 :自定义容器时记得向子树提供正确CompositionLocal。
6. 自检清单
- 新 UI 是否 优先
MaterialTheme.typography+colorScheme,仅 token 不足时才扩展ComposeDemoTokens? - 深色下 onX 与 X 是否成对检查过可读性?
- 设计稿里的「成功 / 警告 / 错误」是否映射到 语义色 而非一次性 RGB?
- 预览
Preview是否包在ComposeDemoTheme { }内,避免「预览正常、进 App 全黑/全白」?
参考答案(复习用)
- 是 。先
MaterialTheme.typography.*/colorScheme.*;跨模块复用语义再抽到ComposeDemoTokens(如success→tertiary),避免业务文件里Color(0xFF...)。 - 应检查 。浅色用的
onPrimary在深色 scheme 里已重新配对;自检时切换系统深色或强制darkTheme = true看正文与背景对比度。 - 应映射到语义 token (如
error、errorContainer、tertiary),便于深浅色一起换;一次性 RGB 只保留在 Theme 定义文件 或设计工具导出层。 - 是 。
@Preview根节点用与MainActivity相同的ComposeDemoTheme { YourScreen() },否则 Preview 可能仍用默认 M3 或未套colorScheme,与真机不一致。
源码仓库 :ComposeDemo(分支
main)