在现有应用中引入 Compose 时,您需要迁移 Material XML 主题,以便对 Compose 组件使用
MaterialTheme。这意味着应用的主题将会有 2 个可信来源:基于 View 的主题以及 Compose
主题。样式上的任何更改都需要在多处实施。应用完全迁移到 Compose 后,请移除 XML 主题。
您可以使用 Material Theme Builder 工具迁移颜色。
当您开始从 XML 迁移到 Compose 时,请将主题迁移到 Material 3 Compose 主题。
术语库
| 术语 | 定义 |
|---|---|
MaterialTheme |
可组合函数,用于为 Compose 界面组件提供主题(颜色、排版、形状)。 |
Shapes |
Compose 对象,用于为 MaterialTheme 定义自定义组件形状。 |
Typography |
Compose 对象,用于为 MaterialTheme 定义自定义文本样式(字体系列、大小、粗细)。 |
ColorScheme |
Compose 对象,用于为 MaterialTheme 定义自定义配色方案。 |
| XML 主题 | 在 XML 文件中定义的 Android 主题系统,由 View 系统使用。 |
限制
在迁移之前,请注意以下限制:
- 本指南仅重点介绍如何迁移到 Material 3。如需了解如何从 替代设计系统进行迁移,请参阅 Material 2 或 Compose 中的自定义设计系统。
- 最终目标是完全迁移到 Compose,这样便可以移除 XML 主题。本指南介绍了如何迁移,但未介绍如何最终移除 XML 主题。
第 1 步:评估设计系统
确定 XML View 项目中使用的设计系统。 分析迁移路径和必要步骤,以便在 Compose 中将现有设计系统迁移到 Material 3。
第 2 步:确定主题源文件
在 XML 中,您需要编写 ?attr/colorPrimary。在 Compose 中,您可以使用 MaterialTheme.* 访问主题值:
确定并找到主题所需的所有 XML 资源和文件:浅色和深色配色方案和限定符、主题、形状、尺寸、排版、样式和其他相关文件。
字符串等资源可以按原样重复使用,无需迁移。
第 3 步:迁移颜色
关键原则: XML 使用命名十六进制颜色。
Material 3 使用 语义角色(例如,primary、onPrimary、surface)。停止按十六进制命名颜色;按角色命名颜色。
示例:
| XML 颜色名称 | Material 3 角色 |
|---|---|
colorPrimary |
primary |
colorPrimaryDark / colorPrimaryVariant |
primaryContainer 或 secondary |
colorAccent |
secondary 或 tertiary |
colorOnPrimary |
onPrimary |
android:colorBackground |
background |
colorSurface |
surface |
colorOnSurface |
onSurface |
colorError |
error |
colorOnError |
onError |
colorOutline |
outline |
colorSurfaceVariant |
surfaceVariant |
colorOnSurfaceVariant |
onSurfaceVariant |
将深色和浅色配色方案从 XML 迁移到 Material 3 Compose 中的等效配色方案。
第 4 步:迁移自定义形状和排版
如果您的应用使用自定义形状:
- 在 Compose 代码中,定义
Shapes对象以复制 XML 形状定义。 将此
Shapes对象提供给MaterialTheme。如需了解详情,请参阅形状。
- 在 Compose 代码中,定义
如果您的应用使用自定义排版:
- 在 Compose 代码中,定义
Typography对象以复制 XML 文本样式和字体定义。 将此
Typography对象提供给MaterialTheme。如需了解详情,请参阅排版。
- 在 Compose 代码中,定义
| Compose 角色 | XML 名称 |
|---|---|
displayLarge |
TextAppearance.Material3.DisplayLarge |
displayMedium |
TextAppearance.Material3.DisplayMedium |
displaySmall |
TextAppearance.Material3.DisplaySmall |
headlineLarge |
TextAppearance.Material3.HeadlineLarge |
headlineMedium |
TextAppearance.Material3.HeadlineMedium |
headlineSmall |
TextAppearance.Material3.HeadlineSmall |
titleLarge |
TextAppearance.Material3.TitleLarge |
titleMedium |
TextAppearance.Material3.TitleMedium |
titleSmall |
TextAppearance.Material3.TitleSmall |
bodyLarge |
TextAppearance.Material3.BodyLarge |
bodyMedium |
TextAppearance.Material3.BodyMedium |
bodySmall |
TextAppearance.Material3.BodySmall |
labelLarge |
TextAppearance.Material3.LabelLarge |
labelMedium |
TextAppearance.Material3.LabelMedium |
labelSmall |
TextAppearance.Material3.LabelSmall |
第 5 步:迁移样式 (styles.xml)
XML 样式 (styles.xml) 系统定义了以下内容的样式和外观:
- 窗口和对话框的微件、组件、主题
- 排版
- 主题和叠加层
- 形状
XML View 和组件组合了多个属性来创建样式。 它们通过以下两种不同的方式从 styles.xml 设置样式:
- 在 XML View 中直接且明确地设置“style="@style/..."
- 将样式间接且隐式地设置为较大主题 (theme.xml) 的一部分
样式在 Compose 中没有 直接 等效项,而是作为以下内容传递给可组合项: 参数或修饰符,使用 AppTheme 中定义的新实验性 Styles API,或者通过创建 具有已定义样式的分层可重复使用的可组合项变体。
提供单独的 @Composable 函数,这些函数根据样式和基本组件命名,以表示这些组件的样式和用例的差异。
- 模式: 如果 XML 元素使用自定义样式
(例如,
style="@style/MyPrimaryButton"), 请勿尝试内联复制该样式。而是建议创建特定的可组合项。 - 示例:
- XML:
<Button style="@style/MyPrimaryButton" ... /> - Compose:
MyPrimaryButton(onClick = { ... })
- XML:
- 常见属性组: 如果样式设置了常见修饰符(例如,内边距 + 高度),请将其提取到可读的扩展属性或共享的 Modifier 变量中。
常见示例
| XML | Compose |
|---|---|
Theme.Material3.* |
MaterialTheme(colorScheme, typography, shapes) { } |
TextAppearance.Material3.BodyMedium |
TextStyle(...) 在 Typography(bodyMedium = ...) 中定义 |
ShapeAppearance.*.SmallComponent |
Shapes(small = RoundedCornerShape(X.dp)) |
Widget.Material3.Button |
Button(colors = ButtonDefaults.buttonColors(...)) |
Widget.Material3.CardView |
Card(shape=..., elevation=..., colors=...) |
Widget.*.TextInputLayout.OutlinedBox |
OutlinedTextField(colors = OutlinedTextFieldDefaults.colors(...)) |
Widget.*.Chip.Filter |
FilterChip(colors = FilterChipDefaults.filterChipColors(...)) |
Widget.*.Toolbar.Primary |
TopAppBar(colors = TopAppBarDefaults.topAppBarColors(...)) |
Widget.*.FloatingActionButton |
FloatingActionButton(containerColor = ...) |
backgroundTint |
containerColor 在 ComponentDefaults.ComponentColors() 中 |
android:textColor |
contentColor 在 ComponentDefaults.ComponentColors() 中 |
cornerRadius |
shape = RoundedCornerShape(X.dp) |
android:elevation |
elevation = ComponentDefaults.elevation(defaultElevation = X.dp) |
android:padding |
contentPadding = PaddingValues(...) 或 Modifier.padding() |
android:minHeight |
Modifier.heightIn(min = X.dp) |
strokeColor + strokeWidth |
border = BorderStroke(width, color) |
android:textSize |
fontSize = X.sp 在 TextStyle 中 |
第 6 步:验证主题迁移
始终使用原始 XML 主题中的现有主题值作为 Compose 中新 Material 主题的可信来源。 切勿在迁移期间创建新的主题值,以保持品牌一致性并避免视觉回归。
验证所有新的 Compose 主题值是否与现有 XML 值匹配。 请勿对任何迁移的值进行硬编码。