Jetpack Compose 提供了 Material Design 3 的实现,这是 Material Design 的下一个演变阶段。Material 3 包括更新的主题、组件和 Material You 个性化功能(如动态颜色),旨在与 Android 12 及更高版本上的新视觉风格和系统 UI 保持一致。
下面,我们使用 Reply 示例应用 演示了 Material Design 3 的实现。Reply 示例完全基于 Material Design 3。
依赖项
要在您的 Compose 应用中开始使用 Material 3,请将 Compose Material 3 依赖项添加到您的 build.gradle
文件中
implementation "androidx.compose.material3:material3:$material3_version"
添加依赖项后,您可以开始向您的应用添加 Material Design 系统,包括颜色、排版和形状。
实验性 API
一些 M3 API 被认为是实验性的。在这种情况下,您需要在函数或文件级别使用 ExperimentalMaterial3Api
注解选择加入
// import androidx.compose.material3.ExperimentalMaterial3Api @Composable fun AppComposable() { // M3 composables }
Material 主题
M3 主题包含以下子系统:配色方案、排版和形状。当您自定义这些值时,您的更改会自动反映在您用于构建应用的 M3 组件中。
Jetpack Compose 使用 M3 MaterialTheme
可组合项实现了这些概念
MaterialTheme( colorScheme = /* ... typography = /* ... shapes = /* ... ) { // M3 app content }
要为您的应用内容设置主题,请定义特定于您的应用的配色方案、排版和形状。
配色方案
配色方案的基础是一组五种关键颜色。每种颜色都与一个包含 13 种色调的色调调色板相关联,这些色调由 Material 3 组件使用。例如,这是 Reply 浅色主题的配色方案
详细了解配色方案和颜色角色。
生成配色方案
虽然您可以手动创建自定义 ColorScheme
,但通常使用来自您的品牌的源颜色生成一个更容易。 Material Theme Builder 工具允许您执行此操作,并可以选择导出 Compose 主题代码。生成以下文件
Color.kt
包含主题的颜色,其中定义了浅色和深色主题颜色的所有角色。
val md_theme_light_primary = Color(0xFF476810) val md_theme_light_onPrimary = Color(0xFFFFFFFF) val md_theme_light_primaryContainer = Color(0xFFC7F089) // .. // .. val md_theme_dark_primary = Color(0xFFACD370) val md_theme_dark_onPrimary = Color(0xFF213600) val md_theme_dark_primaryContainer = Color(0xFF324F00) // .. // ..
Theme.kt
包含浅色和深色配色方案以及应用主题的设置。
private val LightColorScheme = lightColorScheme( primary = md_theme_light_primary, onPrimary = md_theme_light_onPrimary, primaryContainer = md_theme_light_primaryContainer, // .. ) private val DarkColorScheme = darkColorScheme( primary = md_theme_dark_primary, onPrimary = md_theme_dark_onPrimary, primaryContainer = md_theme_dark_primaryContainer, // .. ) @Composable fun ReplyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { val colorScheme = if (!darkTheme) { LightColorScheme } else { DarkColorScheme } MaterialTheme( colorScheme = colorScheme, content = content ) }
要支持浅色和深色主题,请使用 isSystemInDarkTheme()
。根据系统设置,定义要使用的配色方案:浅色或深色。
动态配色方案
动态颜色 是 Material You 的关键部分,其中算法从用户的墙纸中派生出自定义颜色,以应用于其应用和系统 UI。此调色板用作生成浅色和深色配色方案的起点。
动态颜色在 Android 12 及更高版本上可用。如果动态颜色可用,您可以设置动态 ColorScheme
。否则,您应该回退到使用自定义的浅色或深色 ColorScheme
。
ColorScheme
提供了构建器函数来创建动态 浅色 或 深色 配色方案
// Dynamic color is available on Android 12+ val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S val colors = when { dynamicColor && darkTheme -> dynamicDarkColorScheme(LocalContext.current) dynamicColor && !darkTheme -> dynamicLightColorScheme(LocalContext.current) darkTheme -> DarkColorScheme else -> LightColorScheme }
颜色用法
您可以通过 MaterialTheme.colorScheme
访问应用中的 Material 主题颜色
Text( text = "Hello theming", color = MaterialTheme.colorScheme.primary )
每个颜色角色可以在各种位置使用,具体取决于组件的状态、突出程度和强调。
- Primary 是基础颜色,用于主要组件,例如突出的按钮、活动状态和高亮表面的色调。
- Secondary 关键颜色用于 UI 中不太突出的组件,例如筛选器芯片,并扩展了颜色表达的机会。
- Tertiary 关键颜色用于派生对比色调的角色,这些角色可用于平衡 Primary 和 Secondary 颜色,或将注意力增强到某个元素上。
Reply 示例应用设计在 Primary-container 之上使用 on-primary-container 颜色来强调所选项目。
Card( colors = CardDefaults.cardColors( containerColor = if (isSelected) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceVariant ) ) { Text( text = "Dinner club", style = MaterialTheme.typography.bodyLarge, color = if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer else MaterialTheme.colorScheme.onSurface, ) }
在这里,您可以看到在 Reply 导航抽屉中如何使用 Secondary 和 Tertiary container 颜色与之形成对比,以创建强调和重点。
排版
Material Design 3 定义了一个字体比例,包括已从 Material Design 2 中改编的文本样式。命名和分组已简化为:显示、标题、主体和标签,每个都有大、中和小尺寸。
M3 | 默认字体大小/行高 |
displayLarge |
Roboto 57/64 |
displayMedium |
Roboto 45/52 |
displaySmall |
Roboto 36/44 |
headlineLarge |
Roboto 32/40 |
headlineMedium |
Roboto 28/36 |
headlineSmall |
Roboto 24/32 |
titleLarge |
新 - Roboto Medium 22/28 |
titleMedium |
Roboto Medium 16/24 |
titleSmall |
Roboto Medium 14/20 |
bodyLarge |
Roboto 16/24 |
bodyMedium |
Roboto 14/20 |
bodySmall |
Roboto 12/16 |
labelLarge |
Roboto Medium 14/20 |
labelMedium |
Roboto Medium 12/16 |
labelSmall |
新 Roboto Medium,11/16 |
定义排版
Compose 提供了 M3 Typography
类——以及现有的 TextStyle
和 与字体相关的 类——来模拟 Material 3 字体比例。Typography
构造函数为每种样式提供了默认值,因此您可以省略任何您不想自定义的参数
val replyTypography = Typography( titleLarge = TextStyle( fontWeight = FontWeight.SemiBold, fontSize = 22.sp, lineHeight = 28.sp, letterSpacing = 0.sp ), titleMedium = TextStyle( fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.15.sp ), // .. ) // ..
您的产品可能不需要 Material Design 字体比例中的所有 15 种默认样式。在此示例中,为减少的集合选择了五种大小,而其余的则被省略。
您可以通过更改 TextStyle
和 与字体相关的 属性(如 fontFamily
和 letterSpacing
)的默认值来自定义您的排版。
bodyLarge = TextStyle( fontWeight = FontWeight.Normal, fontFamily = FontFamily.SansSerif, fontStyle = FontStyle.Italic, fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.15.sp, baselineShift = BaselineShift.Subscript ),
定义好 Typography
后,将其传递给 M3 MaterialTheme
MaterialTheme( typography = replyTypography, ) { // M3 app Content }
使用文本样式
您可以通过使用 MaterialTheme.typography
检索提供给 M3 MaterialTheme
可组合项的排版
Text( text = "Hello M3 theming", style = MaterialTheme.typography.titleLarge ) Text( text = "you are learning typography", style = MaterialTheme.typography.bodyMedium )
您可以阅读有关 Material 指南中应用排版的更多信息。
形状
Material 表面可以以不同的形状显示。形状吸引注意力、识别组件、传达状态并表达品牌。
形状比例定义了容器角的样式,提供了从正方形到完全圆形的圆角范围。
定义形状
Compose 提供了 M3 Shapes
类,并扩展了参数以支持新的 M3 形状。M3 形状比例更像 字体比例,能够在整个 UI 中表达各种形状。
形状有不同的尺寸
- 特小
- 小
- 中
- 大
- 特大
默认情况下,每个形状都有一个默认值,但您可以覆盖这些值
val replyShapes = Shapes( extraSmall = RoundedCornerShape(4.dp), small = RoundedCornerShape(8.dp), medium = RoundedCornerShape(12.dp), large = RoundedCornerShape(16.dp), extraLarge = RoundedCornerShape(24.dp) )
定义好 Shapes
后,您可以将其传递给 M3 MaterialTheme
MaterialTheme( shapes = replyShapes, ) { // M3 app Content }
使用形状
您可以为 MaterialTheme
中的所有组件自定义形状比例,也可以在每个组件的基础上进行自定义。
应用具有默认值的 Medium 和 Large 形状
Card(shape = MaterialTheme.shapes.medium) { /* card content */ } FloatingActionButton( shape = MaterialTheme.shapes.large, onClick = { } ) { /* fab content */ }
还有其他两种形状——RectangleShape
和 CircleShape
——它们是 Compose 的一部分。RectangleShape 没有边框半径,而 CircleShape 显示完全圆形的边缘
Card(shape = RectangleShape) { /* card content */ } Card(shape = CircleShape) { /* card content */ }
以下示例演示了一些应用了默认形状值的组件
您可以阅读有关 Material 指南中应用形状的更多信息。
强调
M3 中的强调是使用颜色及其 on-color 组合的变化提供的。在 M3 中,有两种方法可以为您的 UI 添加强调
- 使用 surface、surface-variant 和 background 以及来自扩展的 M3 颜色系统的 on-surface、on-surface-variants 颜色。例如,surface 可以与 on-surface-variant 一起使用,而 surface-variant 可以与 on-surface 一起使用,以提供不同级别的强调。
- 为文本使用不同的字体粗细。上面,您看到可以为我们的字体比例提供自定义粗细,以提供不同的强调。
bodyLarge = TextStyle( fontWeight = FontWeight.Bold ), bodyMedium = TextStyle( fontWeight = FontWeight.Normal )
海拔高度
Material 3 主要使用色调颜色叠加来表示海拔高度。这是一种区分容器和表面的新方法——增加色调海拔高度使用更突出的色调——以及阴影。
Material 3 中深色主题中的叠加颜色也已更改为色调颜色叠加。叠加颜色来自 Primary 颜色插槽。
M3 的 Surface(大多数 M3 组件背后的支持性可组合项)同时支持色调和阴影海拔。
Surface( modifier = Modifier, tonalElevation = /*... shadowElevation = /*... ) { Column(content = content) }
Material 组件
Material Design 提供了一套丰富的 Material 组件(如按钮、芯片、卡片、导航栏),这些组件已经遵循 Material 主题,可以帮助您创建美观的 Material Design 应用。您可以立即开始使用具有默认属性的组件。
Button(onClick = { /*..*/ }) { Text(text = "My Button") }
M3 提供了许多相同组件的不同版本,可根据强调和关注度用于不同的角色。
- 扩展浮动操作按钮,用于最高强调的操作
ExtendedFloatingActionButton( onClick = { /*..*/ }, modifier = Modifier ) { Icon( imageVector = Icons.Default.Edit, contentDescription = stringResource(id = R.string.edit), ) Text( text = stringResource(id = R.string.add_entry), ) }
- 填充按钮,用于高强调的操作
Button(onClick = { /*..*/ }) { Text(text = stringResource(id = R.string.view_entry)) }
- 文本按钮,用于低强调的操作
TextButton(onClick = { /*..*/ }) { Text(text = stringResource(id = R.string.replated_articles)) }
您可以阅读更多关于 Material 按钮和其他组件 的信息。Material 3 提供了各种组件套件,例如按钮、应用栏、导航组件,这些组件专为不同的用例和屏幕尺寸而设计。
导航组件
Material 还提供了一些导航组件,可帮助您根据不同的屏幕尺寸和状态实现导航。
NavigationBar
用于紧凑型设备,当您想要定位 5 个或更少的目的地时。
NavigationBar(modifier = Modifier.fillMaxWidth()) { Destinations.entries.forEach { replyDestination -> NavigationBarItem( selected = selectedDestination == replyDestination, onClick = { }, icon = { } ) } }
NavigationRail
用于小型到中型平板电脑或横向模式下的手机。它为用户提供人体工程学设计,并改善了这些设备的用户体验。
NavigationRail( modifier = Modifier.fillMaxHeight(), ) { Destinations.entries.forEach { replyDestination -> NavigationRailItem( selected = selectedDestination == replyDestination, onClick = { }, icon = { } ) } }
Reply 使用两者进行默认主题设置,为所有设备尺寸提供沉浸式用户体验。
NavigationDrawer
用于中型到大型平板电脑,在这些平板电脑上有足够的空间显示详细信息。您可以同时使用 PermanentNavigationDrawer
或 ModalNavigationDrawer
以及 NavigationRail
。
PermanentNavigationDrawer(modifier = Modifier.fillMaxHeight(), drawerContent = { Destinations.entries.forEach { replyDestination -> NavigationRailItem( selected = selectedDestination == replyDestination, onClick = { }, icon = { }, label = { } ) } }) { }
导航选项增强了用户体验、人体工程学和可达性。您可以在 Compose 自适应代码实验室 中了解更多关于 Material 导航组件的信息。
自定义组件的主题
M3 鼓励个性化和灵活性。所有组件都应用了默认颜色,但公开了灵活的 API 以在需要时自定义其颜色。
大多数组件(如卡片和按钮)都提供一个默认对象,该对象公开了颜色和海拔接口,可以修改这些接口以自定义您的组件。
val customCardColors = CardDefaults.cardColors( contentColor = MaterialTheme.colorScheme.primary, containerColor = MaterialTheme.colorScheme.primaryContainer, disabledContentColor = MaterialTheme.colorScheme.surface, disabledContainerColor = MaterialTheme.colorScheme.onSurface, ) val customCardElevation = CardDefaults.cardElevation( defaultElevation = 8.dp, pressedElevation = 2.dp, focusedElevation = 4.dp ) Card( colors = customCardColors, elevation = customCardElevation ) { // m3 card content }
您可以阅读更多关于 自定义 Material 3 的信息。
系统 UI
Material You 的某些方面来自 Android 12 及更高版本上的新视觉风格和系统 UI。有两个主要领域发生了变化:涟漪和过度滚动。无需执行任何额外工作即可实现这些更改。
涟漪
涟漪现在使用微妙的闪烁效果来照亮按下时的表面。 Compose Material Ripple 在 Android 上使用平台 RippleDrawable,因此闪烁涟漪在 Android 12 及更高版本上可用于所有 Material 组件。
过度滚动
过度滚动现在在滚动容器的边缘使用 拉伸效果。拉伸过度滚动在滚动容器可组合项(例如,LazyColumn
、LazyRow
和 LazyVerticalGrid
)中默认启用,在 Compose Foundation 1.1.0 及更高版本中,无论 API 级别如何。
可访问性
内置于 Material 组件中的辅助功能标准旨在为包容性产品设计提供基础。了解您产品的辅助功能可以增强所有用户的可用性,包括视力低下、失明、听力障碍、认知障碍、运动障碍或情境性残疾(如骨折)的用户。
颜色辅助功能
动态颜色旨在满足颜色对比度的辅助功能标准。色调调色板系统对于默认情况下使任何配色方案都可访问至关重要。
Material 的颜色系统提供标准的色调值和测量值,可用于满足可访问的颜色对比度比率。
所有 Material 组件和动态主题都已使用上述颜色角色,这些角色来自一组 色调调色板,这些调色板经过选择以满足辅助功能要求。但是,如果您正在自定义组件,请确保使用适当的颜色角色并避免不匹配。
在主要颜色之上使用 on-primary,在主要容器之上使用 on-primary-container,其他强调色和中性色也一样,以便为用户提供可访问的颜色对比度。
在主要颜色之上使用三级容器会为用户提供对比度较差的按钮。
// ✅ Button with sufficient contrast ratio Button( onClick = { }, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary ) ) { } // ❌ Button with poor contrast ratio Button( onClick = { }, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.tertiaryContainer, contentColor = MaterialTheme.colorScheme.primaryContainer ) ) { }
排版辅助功能
M3 类型比例更新了静态类型斜坡和值,以提供一个简化但动态的尺寸类别框架,该框架可在设备之间缩放。
例如,在 M3 中,可以根据设备上下文(例如手机或平板电脑)为“显示小”分配不同的值。
大屏幕
Material 提供了关于自适应布局和折叠屏的指导,以使您的应用可访问并改善用户手持大型设备的人体工程学。
Material 提供了不同类型的 导航,以帮助您为大型设备提供更好的用户体验。
您可以了解有关 Android 大屏幕应用质量指南 的更多信息,并查看我们的 Reply 示例 以了解自适应和可访问的设计。
了解更多
要了解有关 Compose 中 Material 主题的更多信息,请查看以下资源
示例应用
文档
API 参考和源代码
视频
为您推荐
- 注意:当 JavaScript 关闭时,会显示链接文本
- 从 Compose 中的 Material 2 迁移到 Material 3
- Compose 中的 Material Design 2
- Compose 中的自定义设计系统