Material You is the development direction of the next generation of Material Design, and it is also a new design vision: it is convenient for you to create personalized styles, meet various needs and adapt to various screens; Jetpack Compose is used to build native A new, modern toolkit for the Android interface that helps you build better apps faster.
You may be familiar with the existing Compose Material library, which is based on the Material Design 2 specification and includes features such as Material Themes, Material Components, and Dark Themes. The new Compose Material 3 Jetpack library, , now in alpha, is based on the Material Design 3 specification and includes updated themes, components, and Material You personalization features like dynamic color matching, designed to work with the new Android 12 visual styles Compatible with the system interface. Next, we will use Jetchat to illustrate how to apply Material Design 3 and Material You.
If you prefer to see this through video, check it out here:
https://www.bilibili.com/video/BV14i4y1f71K/?aid=551474117&cid=506247446&page=1
△ Use Compose Material 3 in the application
Jetchat is a sample chat app built with Jetpack Compose, currently using themes and components from Material Design 2. In Jechat, we will be applying updates to the Compose Material 3 library provided by our designers, including a wider range of tint colors, recent updates to components, and even dynamic color matching to personalize the app, making it more beautiful.
△ Jetchat application
Before we start, we first need to add the Material 3 dependencies to the module's build.gradle file:
implementation 'androidx.compose.material3:material3:1.0.0-alpha01'
MaterialTheme
Let's take a look at MaterialTheme first. The existing MaterialTheme composable is an implementation of Material Design 2 that enables theming of Material 2 components throughout the app by adjusting the color, typography, and shape systems. We've introduced a new version of MaterialTheme for Material Design 3, where Material 3 components can be themed by adjusting the color scheme and typography system, and the ability to update Shape will be added shortly.
import androidx.compose.material3.MaterialTheme
@Composable
fun MaterialTheme (
colorScheme: ColorScheme,
typography: Typography,
// 更新 Shape 的功能即将到来
content: @Composable () -> Unit
)
First, let's look at the color scheme. Material Design 3 subdivides colors into specifically named color slots. For example, Primary, Background and Error used by Material 3 components, these color slots together form a color scheme. Some of the color slots are from Material Design 2, and some new ones are also introduced to expand the overall palette. These color slots all contain beautiful new default base colors that can be applied on both light and dark themes.
△ The green box is the newly added color slot in Material You
The colors above are taken from a set of tint palettes, for example, let's take a look at the Primary color slot. This color slot uses color values from the different hues in the Primary hue palette, and selects the appropriate hues based on the light and dark themes to meet accessibility requirements.
△ Primary color slot
Compose models this using the new ColorScheme class, whose parameters are named after the color slots in the Material Design 3 color scheme. You can use the lightColorScheme function to create a ColorScheme instance with a light base value; you can also override the default with a custom color, or use darkColorScheme to set a dark default base value; you can also use the isSystemInDarkTheme utility function to set the light and dark color based on the system settings. Toggle between dark color schemes.
val AppLightColorScheme = lightColorScheme (
primary = Color(...),
// secondary、tertiary 等等
// 具有浅色基准值的 ColorScheme 实例
)
val AppDarkColorScheme = darkColorScheme(
// primary、secondary、tertiary 等等
// 具有深色基准值的 ColorScheme 实例
)
val dark = isSystemInDarkTheme()
val colorScheme = if (dark) AppDarkColorScheme else AppLightColorScheme
// 将 colorScheme 作为参数传递给 MaterialTheme。
MaterialTheme (
colorScheme = colorScheme,
// 字型
) {
// 应用内容
}
Next, let's take a look at Jetchat's color scheme. Jetchat's color scheme was generated by the MaterialTheme Builder tool, we used blue and yellow from the Jetchat brand colors as the source of Primary, Secondary, and Tertiary colors to generate a Material 3 color scheme that is very suitable for Jetchat, which covers the use of light color and dark theme colors. The brand colors used by Jetchat are taken from a set of custom tint palettes generated by the MaterialTheme Builder tool, and the image below shows the Primary color, the tint palette of blue, and the matching Primary color slot in the color scheme.
△ Jechat color scheme generated in the MaterialTheme Builder tool
To implement the Jechat color scheme, first declare the colors using the Color class. The MaterialTheme Builder tool can also export the generated code for you. Next, you can declare the Jetchat light and dark color schemes with corresponding color values.
// 来自名为'Blue'的色调调色盘的 Primary 颜色
val Blue10 = Color (0xFF000965)
val Blue20 = Color (0xFF00159E)
val Blue30 = Color (0xFF0023DA)
val Blue40 = Color (0xFF1E40FF)
val Blue80 = Color (0xFFBBC3FF)
val Blue90 = Color (0xFFDDE0FF)
val JetchatLightColorScheme = lightColorScheme (
primary = Blue40,
onPrimary = Color.White,
primaryContainer = Blue90,
onPrimaryContainer = Blue10,
// secondary、tertiary、surface 等等
)
val JetchatDarkColorScheme = darkColorScheme (
primary = Blue80,
onPrimary = Blue20,
primaryContainer = Blue30,
onPrimaryContainer = Blue90,
// secondary、tertiary、surface 等等
)
We've created a new composable function for the Jechat theme that takes a parameter to determine the dark theme and an application content parameter, allowing us to switch between Jetchat's light and dark color schemes. Next, we pass the colorScheme value and content to the inner MaterialTheme composable, which allows us to encapsulate the Jechat content and provide a theme for the app.
@Composable
fun JetchatTheme (
dark: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (dark) JetchatDarkColorScheme else JetchatLightColorScheme
MaterialTheme (
colorScheme = colorScheme,
content = content,
)
}
Let's take a look at the Jetchat dialog interface, where different parts of the interface use different color slots in the color scheme. For example, depending on the user, use the primary color or tertiary color for the border color of the message avatar. Here the theme color value is accessed using MaterialTheme.colorScheme.
△ Jetchat dialogue interface
@Composable
fun Message(...) {
val avatarBorderColor = if (isUserMe) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.tertiary
}
...
}
dynamic color matching
Next, let's understand what dynamic color matching is. Dynamic color matching is an important part of Material You, where algorithms extract custom colors from the user's wallpaper and apply them to app and system interfaces, which you can use as a starting point to generate complete light and dark color schemes.
△ The color scheme of Jetchat changes with the wallpaper set by the user
Dynamic ColorScheme is available in Android 12 and above, to implement Dynamic ColorScheme in Compose, you need to check Build.VERSION.SDK first. If dynamic color matching is available, we can set a dynamic ColorScheme; if not, we can fall back to using lightColorScheme or darkColorScheme as before:
val dynamic = Build.VERSION.SOK_INT >= Build.VERSION_CODES.S
val colorScheme = if (dynamic) {
val context = LocalContext.current
// 使用 dynamicLightColorScheme 函数创建具有浅色动态值的 ColorScheme 实例
// 或使用 dynamicDarkColorScheme 创建具有深色动态值的实例
// 传入 Context 以便从 Android 系统获取动态配色资源
if (dark) dynamiclightColorScheme(context) else dynamicDarkColorScheme(context)
} else {
// 使用 lightColorScheme 或者 darkColorScheme
}
Currently, Jetchat has been using the brand's blue color scheme, but we hope to add support for wallpaper-based dynamic color schemes to match the user's personal adjustment. In this example, the tint palette is generated based on the colors in the wallpaper, and the dynamic color scheme is derived from these tint palettes, which include colors for light and dark themes.
To achieve this in Jechat, we first update JechatTheme to add a new parameter for dynamic color matching, and then use that dynamic coloring parameter to set a dynamic ColorScheme, or fall back to the brand's blue color scheme when unavailable. Pass the colorScheme value and content to the inner MaterialTheme composable as before.
@Composable
fun JetchatTheme (
dark: Boolean = isSystemInDarkTheme (),
dynamic: Boolean = Build. VERSION.SDK_INT >= Build.VERSION_CODES.S,
content: @Composable () -> Unit
) {
// ColorScheme 配置以及 MaterialTheme
val colorScheme = if (dynamic) {
val context = LocalContext.current
if (dark) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
} else {
if (dark) JetchatDarkColor Scheme else Jetchat Light Color Scheme
}
MaterialTheme(
colorScheme = colorScheme,
content = content,
)
}
Now, on Android 12 and higher, the Jetchat interface automatically adjusts color based on the user's wallpaper, providing a beautiful, brand-friendly experience in both light and dark themes.
△ Dynamic color matching that automatically adapts to the dark and light theme
typeset
Now that we understand color schemes, let's take a look at typography. Material Design 3 has new font specifications, including text styles adapted from Material Design 2. The naming and grouping of styles is simplified to Display, Headline, Heading, Body, and Labels; each grouping has large, medium, and small fonts.
△ Material 3 and Material 2 font style grouping
Compose uses the new Typography class to model typography, whose parameters are named after the styles in the Material Design 3 typography. We can create a Typography instance with the Roboto base value, override the default with a custom text style, and finally pass Typography as a parameter to MaterialTheme.
import androidx.compose.material3.Typography
class Typography (
val displayLarge: TextStyle,
val displayMedium: TextStyle,
val displaySmall: TextStyle,
// headlineLarge、titleMedium、bodySmall 等等
)
val AppTypography = Typography (
bodyLarge = TextStyle(...),
// displayLarge、titleMedium、labelSmall 等等
// 使用默认的 Roboto 基准值
)
MaterialTheme (
typography = AppTypography,
// colorScheme
) {
//App content
}
Let's take another look at Jetchat's typography. The designers provided us with new brand font specifications, using custom fonts Montserrat and Karla:
△ Font specifications used by Jetchat
We first declare these fonts using the FontFamily class, which will hold an instance of the Font class. We can construct the Font class with the font resource ID and font weight, then use the Typography class to declare the Jechat font styles, and the TextStyle class to override each text style, including our font, font size, font weight, and other typographic values. Finally, again, pass Typography as a parameter to MaterialTheme:
val MontserratFontFamily = FontFamily (
Font(R.font.montserrat_regular),
Font(R.font montserrat_light, FontWeight Light),
Font(R.font.montserrat_semibold, FontWeight. SemiBold)
)
val KarlaFontFamily = FontFamily (
Font(R.font.karla_regular),
Font(R.font.karla_bold, FontWeight. Bold)
)
val JetchatTypography = Typography(
bodyLarge = TextStyle(
fontFamily = KarlaFontFamily,
fontWeight = FontWeight. Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
// titleMedium、labelSmall 等等
)
MaterialTheme (
typography = JetchatTypography,
// colorScheme、content
)
Let's take a look at the Jechat dialog interface, each part of the interface uses a different text style from the Jechat font specification. For example, the contact and timestamp in the message use the titleMedium and labelSmall styles respectively. They access theme font values through the MaterialTheme.typography representation.
△ Dialogue interface font settings
@Composable
fun Message(...) {
…
Text (style = MaterialTheme.typography.titleMedium, ...)
…
Text (style = MaterialTheme.typography.labelSmall, ...)
}
height
Now that we've learned about the theme-related updates in Material 3, let's take a look at another key update to Material Design - height. In a nutshell, in Material 2, a shadow was used to represent height, while in Material 3, a tint color overlay was used instead. This is a new way of distinguishing between containers and surfaces, and increasing the shade height makes the shades more prominent.
The height overlay was part of the dark theme in Material 2 and has also been changed to a tint color overlay in Material 3.
△ M2 and M3 mid-altitude system effect comparison
Let's take the Surface component as an example. Surface is a composable that supports most Material components. The existing Surface composable implements the Material Design 2 height system. In Material Design 2 Surface receives an elevation parameter and handles shadow and overlay rendering in dark themes. We introduced a new version of Surface for Material Design 3 that accepts a tonalElevation parameter and handles tonal color overlay rendering in both light and dark themes. Let's see the difference before and after:
△ Surface in Material 2
△ Surface in Material 3
component update
Material 3 brings updates to many components, such as buttons, app bars, dialogs, FABs, and navigation components. These updates take advantage of the new Material 3 theme settings and include the latest updates to each component's specification.
△ Updated components in Material 3
For example BottomNavigation in Material 2. It conforms to the Material Design 2 specification and accepts parameters such as backgroundColor and elevation. The composable was renamed NavigationBar in Material 3, which conforms to the Material Design 3 specification, with the parameters changed to containerColor and tonalElevation to more accurately reflect their purpose.
// Materail 2 中的 NavigationBar
import androidx.compose.material.BottomNavigation
@Composable
fun BottomNavigation (
// M2 默认值
backgroundColor: Color,
elevation: Dp,
…
)
// Materail 3 中的 NavigationBar
import androidx.compose.material3.NavigationBar
@Composable
fun NavigationBar (
// M3 默认值
containerColor: Color,
tonalElevation: Dp,
…
)
△ The style changes before and after the update
Components in Compose Material 3 have been updated a lot, and to give you a complete overview of all the components and how they are implemented, we've updated the Compose Material Catalog app and added a new Material 3 section. Please view the source code on AOSP and download the app in Google Play.
Let's take a look at an example from Jetchat. There is an extended FAB for composing messages on the profile interface, this component has been updated from Material 2 to Material 3 version. This is a simple implementation of the Material 2 version, using the ExtendedFloatingActionButton composable, internally using Icon and Text, the composable, and a custom Primary background color.
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.Text
ExtendedFloatingActionButton(
icon = { Icon(...) },
text = { Text(...) },
backgroundColor = MaterialTheme.colors.primary,
...
)
Material 3's update to this component is shown here, the dependency import for composables has been changed to Material 3, we use the renamed containerColor parameter and the Tertiary color from the Material 3 color scheme.
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
ExtendedFloatingActionButton(
icon = { Icon(...) },
text = { Text(...) },
containerColor = MaterialTheme.colorScheme.tertiary,
...
)
Visual Effects
Some aspects of Material You come from the new Android 12 visual styles and system interface, and two of the big changes are the ripple and scroll effects. The ripple effect now illuminates the surface with a subtle sparkle when pressed, and the scroll effect uses a stretch effect on the edges of the scroll container. Implementing these changes requires no extra work, stretch scrolling is on by default in scroll container composables in Compose Foundation 1.1 and later; the flash ripple available on Android 12 works for all Material components.
△ Ripple effect in M2 and M3
// 拉伸滚动
// 适用于 LazyColumn、Lazy Row、LazyVerticalGrid 等组件
// ComposeFoundation 1.1.0+ 可用
// 闪光波纹
// 适用于所有 Material 2 和 Material 3 组件
// Android 12+ 可用
Interoperability improvements with Android View
Interoperability with Android views is an important part of developing apps with Compose, and we've made some updates in Material 3 to support this. MDC-AndroidCompose Theme Adapter library is a Material component that supports reuse of Android XML themes to facilitate our themeing in Jetpack Compose.
Existing MdcTheme composables are compatible with Material 2 XML themes, and we have also introduced a new Mdc3Theme composable that is compatible with Material 3 XML themes.
△ MDC-AndroidCompose Theme Adapter is a bridge between XML theme and MaterialTheme
epilogue
Now is a great time to try out Compose Material 3 in your Android app, and we've put together a series of resources to help you along the journey. We have a new API document for Compose Material 3 and a new Empty Compose Activity template in Android Studio with updates for Material 3. In addition, we updated the Theming guide in Compose , as well as the Jechat example and Compose Material Catalog app seen earlier, and the MDC-Android ComposeTheme Adapter interoperability library.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。