Jetpack Compose 提供了 Material You 和 Material 3 Expressive(新一代 Material Design)的实现。M3 Expressive 是 Material Design 3 的扩展版本,包含经过研究验证的主题、组件、动效、排版等方面的更新,旨在帮助您打造用户喜爱的、极具吸引力且令人向往的产品。它还支持 Material You 个性化功能,例如动态配色。M3 Expressive 与 Android 16 视觉风格和系统界面相得益彰。
下面,我们以 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 被视为实验性 API。在这种情况下,您需要使用 ExperimentalMaterial3Api 注解在函数或文件级别指定 OptIn:
// 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 主题设置构建器工具执行此操作,并且可以选择导出 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 的关键部分,使用此功能时,算法会从用户的壁纸中派生自定义颜色,以将其应用到其应用和系统界面。此调色板用作生成浅色和深色配色方案的起点。
动态颜色适用于 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 )
每种颜色角色均可在各种位置使用,具体取决于组件的状态、显眼程度和强调效果。
- 主色是基础颜色,用于主要组件,例如显眼的按钮、活动状态和凸起表面的色调。
- 辅色用于界面中不太显眼的组件(例如过滤组件),并可增加颜色表达的机会。
- 第三色用于派生对比强调色角色,这些角色可用于平衡主色和辅色,或者引起用户对某个元素的高度关注。
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 抽屉式导航栏中看到如何使用次要和第三容器颜色进行对比,以创建强调和强调。
排版
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 |
New- 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 |
New 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 Surface 可以用不同的形状显示。形状能够引导用户注意力、区别组件、传达状态以及呈现品牌风格。
形状比例定义了容器拐角的样式,提供从方形到全圆形的各种圆润度。
定义形状
Compose 提供带有扩展参数的 M3 Shapes 类,以支持新的 M3 形状。M3 形状比例更像字体比例,能够在整个界面中呈现丰富多样的形状。
形状有不同的大小:
- 较小
- 小
- 中号
- 大
- 超大
默认情况下,每个形状都有一个默认值,但您可以替换这些值:
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 中的所有组件自定义形状比例,也可以按组件进行自定义。
应用具有默认值的中等和大型形状:
Card(shape = MaterialTheme.shapes.medium) { /* card content */ } FloatingActionButton( shape = MaterialTheme.shapes.large, onClick = { } ) { /* fab content */ }
在 Compose 中,您还可以使用另外两种形状(RectangleShape 和 CircleShape)。矩形没有边框半径,圆形则会显示完整的圆角边缘:
Card(shape = RectangleShape) { /* card content */ } Card(shape = CircleShape) { /* card content */ }
以下示例展示了一些应用了默认形状值的组件:
您可以详细了解有关应用形状的 Material 指南。
强调方式
M3 中的强调效果是通过各种颜色变体及其颜色组合提供的。在 M3 中,您可以通过以下两种方式为界面添加强调效果:
- 同时使用 Surface、surface-variant 和背景以及扩展 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 主要使用色调颜色叠加叠加层来表示高度。这是一种新的方式,用于区分容器和 Surface,增加的色调高度除了使用阴影外,还使用更突出的色调。
在 Material 3 中,深色主题的高度叠加层也更改为色调颜色叠加层。叠加层颜色来自主要颜色槽。
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 还提供了多种导航组件,可帮助您根据不同的屏幕尺寸和状态来实现导航。
当您希望定位到 5 个或更少目的地时,NavigationBar 用于紧凑型设备:
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 = { } ) } }
BottomNavigationBar(左)和 NavigationRail(右)的回复展示在默认主题中同时使用这两种方式进行回复,以便为所有设备尺寸提供沉浸式用户体验。
NavigationDrawer 用于中大型平板电脑,因为您有足够的空间来显示详细信息。您可以将 PermanentNavigationDrawer 或 ModalNavigationDrawer 与 NavigationRail 结合使用。
PermanentNavigationDrawer(modifier = Modifier.fillMaxHeight(), drawerContent = { Destinations.entries.forEach { replyDestination -> NavigationRailItem( selected = selectedDestination == replyDestination, onClick = { }, icon = { }, label = { } ) } }) { }
导航选项可提升用户体验、人体工学设计和可达性。 如需详细了解 Material 导航组件,请参阅 Compose 自适应 Codelab。
自定义组件的主题
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。
系统界面
Material You 的某些方面源自 Android 12 及更高版本上的全新视觉风格和系统界面。发生变化的两个关键方面是涟漪效果和滚动回弹。您无需执行任何额外操作即可实现这些变更。
涟漪
现在,按下时,涟漪会使用微小的火花照射表面。Compose Material Ripple 在 Android 平台上使用 RippleDrawable,因此 Android 12 及更高版本上的所有 Material 组件都支持闪烁涟漪效果。
滚动
现在,滚动回弹会在滚动容器的边缘使用拉伸效果。在 Compose Foundation 1.1.0 及更高版本中,无论 API 级别如何,滚动容器可组合项(例如 LazyColumn、LazyRow 和 LazyVerticalGrid)中默认都会启用拉伸滚动回弹。
无障碍
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 中,可以根据设备上下文(例如手机或平板电脑)为 Display Small 分配不同的值。
大屏设备
Material 提供了有关自适应布局和可折叠设备的指南,可让您的应用更易于访问,并改善用户手持大屏设备时的工效学体验。
Material 提供了不同类型的导航,可帮助您为大屏设备提供更好的用户体验。
您可以详细了解 Android 大屏应用质量指南,并查看我们的 Reply 示例,了解自适应和无障碍设计。
了解详情
如需详细了解 Compose 中的 Material 主题设置,请参阅以下资源:
示例应用
文档
API 参考文档和源代码
视频
为你推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 在 Compose 中从 Material 2 迁移至 Material 3
- Compose 中的 Material Design 2
- Compose 中的自定义设计体系