在现有应用中引入 Compose 时,您需要迁移 Material XML 主题才能对 Compose 组件使用 MaterialTheme。这意味着应用的主题将会有 2 个可信来源:基于 View 的主题以及 Compose 主题。样式上的任何更改都需要在多处实施。应用完全迁移到 Compose 后,请移除 XML 主题。
您可以使用 Material 主题构建器工具迁移颜色。
当您开始从 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 代码中,定义一个
| 撰写角色 | 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 视图和组件会组合多个属性来创建样式。 它们通过两种不同的方式从 styles.xml 设置其样式:
- 直接在 XML 视图中明确设置“style="@style/…"”
- 作为较大主题 (theme.xml) 的一部分,为组件间接和隐式设置样式
样式在 Compose 中没有直接等效项,而是通过以下方式传递:作为可组合项的参数或修饰符,使用 AppTheme 中定义的全新实验性 Styles API,或使用定义的样式创建分层的可重用可组合项变体。
提供根据样式和基本组件命名的单独 @Composable 可组合函数,以表示这些组件的样式和应用场景差异。
- 模式:如果 XML 元素使用自定义样式(例如
style="@style/MyPrimaryButton"),请勿尝试以内嵌方式复制该样式。而是建议创建特定的可组合项。 - 示例:
- XML:
<Button style="@style/MyPrimaryButton" ... /> - Compose:
MyPrimaryButton(onClick = { ... })
- XML:
- 常见属性组:如果样式设置了常见修饰符(例如内边距 + 高度),请将其提取到可读的扩展属性或共享的 Modifier 变量中。
常见示例
| XML | 写邮件 |
|---|---|
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 |
ComponentDefaults.ComponentColors() 中的 containerColor |
android:textColor |
ComponentDefaults.ComponentColors() 中的 contentColor |
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 |
TextStyle 中的 fontSize = X.sp |
第 6 步:验证主题迁移
始终使用原始 XML 主题中的现有主题值作为 Compose 中新 Material 主题设置的可信来源。在迁移过程中,切勿创造新的主题值,以保持品牌一致性并避免视觉效果退化。
验证所有新的 Compose 主题值是否与现有 XML 值匹配。 请勿对任何迁移的值进行硬编码。