Material You is the development direction of the next generation of Material Design, which is also a brand new Design vision: convenient for You to create personalized style Design, meet various needs and adapt to various screens; Jetpack Compose is a new modern toolkit for building native Android interfaces that will help you build better apps faster.

You’re probably 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 available in Alpha, is based on the Material Design 3 specification and includes updated Material You personalization features such as themes, components, and dynamic color matching. Designed to complement the new Android 12 visual style and system interface. Next, we’ll use Jetchat to show how to apply Material Design 3 and Material You.

If you prefer to see this in video, check it out here.

Jetchat is a sample chat application built using Jetpack Compose that currently uses themes and components from Material Design 2. In Jetchat, we’ll be applying an update to the Compose Material 3 library provided by our designers, which includes a wider range of tone colors, recent updates to components, and even dynamic color matching to personalize the app and make it more aesthetically pleasing.

Delta Jetchat application

To start, we need to add Material 3 dependencies to the build.gradle file of our module:

Implementation of 'androidx.com pose. Material3: material3:1.0.0 - alpha01'Copy the code

MaterialTheme

Let’s look at the MaterialTheme first. The existing MaterialTheme composable is an implementation of Material Design 2, which enables theme setting of Material 2 components throughout the application by adjusting the color, typography, and shape system. We have introduced a new version of MaterialTheme for Material Design 3, which can be set to Material 3 component themes by adjusting the color scheme and typography system, and the ability to update Shape will be added soon.

import androidx.compose.material3.MaterialTheme
 
@Composable
fun MaterialTheme (
    colorScheme: ColorScheme,
    typography: Typography.// Shape update is coming soon
    content: @Composable() - >Unit
)
Copy the code

First, let’s look at the color scheme. Material Design 3 subdivides colors into color slots with specific names. Such as the Primary, Background, and Error used by the Material 3 component, these color slots work together to form a color scheme. Some of the color slots came from Material Design 2, while some new color slots were introduced to expand the overall color palette. These color slots contain beautiful new default base colors that can be applied to both light and dark themes.

△ The green box is a new color slot added by Material You

The colors above are taken from a set of color palettes. For example, let’s look at the Primary color slot. The color slot uses color values from different hues in the Primary tone palette and selects corresponding hues based on 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 ColorScheme. You can use the lightColorScheme function to create instances of ColorScheme with light-colored reference values; You can also override the default values with custom colors, or use the darkColorScheme to set the default base values for dark colors. You can also use the isSystemInDarkTheme utility function to switch between light and dark color schemes depending on your system Settings.

valAppLightColorScheme = lightColorScheme ( primary = Color(...) .// Secondary, tertiary, etc
    // Instance of ColorScheme with light-colored reference values
)
 
val AppDarkColorScheme = darkColorScheme(
    // Primary, secondary, tertiary, etc
    // ColorScheme instance with dark reference valueval dark = isSystemInDarkTheme()
val colorScheme = if (dark) AppDarkColorScheme else AppLightColorScheme
 
// Pass the colorScheme as an argument to the MaterialTheme.
MaterialTheme (
    colorScheme = colorScheme,
    / / font
) {
    // Application content
}
Copy the code

Next, let’s take a look at Jetchat’s color scheme. Jetchat’s color scheme is generated by the MaterialTheme Builder tool. We use blue and yellow from Jetchat brand colors as the Primary, Secondary and Tertiary colors sources. A Material 3 color scheme was generated that was perfect for Jetchat, covering colors for both light and dark themes. The brand colors used by Jetchat are taken from a set of custom hue palettes generated by the MaterialTheme Builder tool. The Primary color, the blue hue palette, is shown in the figure below, along with the matching Primary color slots in the color scheme.

△ Jetchat color scheme generated in the MaterialTheme Builder tool

To implement the Jetchat Color scheme, you first declare these colors using the Color class. The MaterialTheme Builder tool can also export the generated code for you. Next, you can declare Jetchat light and dark color schemes using the corresponding color values.

// The Primary color from the hue palette named 'Blue'
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,
    Tertiary, Tertiary, Surface, etc
)
 
val JetchatDarkColorScheme = darkColorScheme (
    primary = Blue80,
    onPrimary = Blue20,
    primaryContainer = Blue30,
    onPrimaryContainer = Blue90,
    Tertiary, Tertiary, Surface, etc
)
Copy the code

We created a new composable function for the Jetchat 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 internal MaterialTheme composable, which enables us to encapsulate the Jetchat content and provide the theme for the application.

@Composable
fun JetchatTheme (
    dark: Boolean = isSystemInDarkTheme(),
    content: @Composable() - >Unit
) {
    val colorScheme = if (dark) JetchatDarkColorScheme else JetchatLightColorScheme
    MaterialTheme (
        colorScheme = colorScheme,
        content = content,
    )
}
Copy the code

Let’s take a look at the Jetchat conversation interface, where different parts of the interface use different color slots in the color scheme. For example, the border color of the message avatar is Primary or Tertiary, depending on the user. Here use MaterialTheme. ColorScheme to visit theme color value.

Jetchat chat interface

@Composable
fun Message(...). {
    val avatarBorderColor = if (isUserMe) {
        MaterialTheme.colorScheme.primary
    } else {
        MaterialTheme.colorScheme.tertiary
    }
    ...
}
Copy the code

Dynamic color

Next, let’s learn what dynamic color matching is. Dynamic color matching is an important part of Material You, which uses algorithms to extract custom colors from a user’s wallpaper and apply them to the app and system interface. You can use this as a starting point to generate complete light and dark color schemes.

Jetchat’s color scheme changes according to the wallpaper you set

Dynamic color matching is available in Android 12 and later, and to implement dynamic ColorScheme in Compose, first check the build.version.sdk. If dynamic color matching is available, we can set dynamic ColorScheme; If not, you 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
    // Use the dynamicLightColorScheme function to create an instance of ColorScheme with light-colored dynamic values
    // Or use the dynamicDarkColorScheme to create an instance with dark dynamic values
    // Pass the Context to get the dynamic color matching resources from the Android system
    if (dark) dynamiclightColorScheme(context) else dynamicDarkColorScheme(context)
} else {
    // Use lightColorScheme or darkColorScheme
}
Copy the code

Currently, Jetchat has been using the branded blue color scheme, but we wanted to add support for wallpapery-based dynamic color schemes to accommodate user customization. In this case, the hue palette is based on the color generation in the wallpaper, and the dynamic color scheme is derived from these hue palettes, which include colors for light and dark themes.

To achieve this in Jetchat, we first update the JetchatTheme to add a new parameter to the dynamic ColorScheme, and then use that dynamic ColorScheme to set the dynamic ColorScheme, or fall back to the brand’s blue ColorScheme when not available. Pass the colorScheme value and content to the internal MaterialTheme composable item as before.

@Composable
fun JetchatTheme (
    dark: Boolean = isSystemInDarkTheme ().dynamic: Boolean = Build. VERSION.SDK_INT >= Build.VERSION_CODES.S,
    content: @Composable() - >Unit
) {
    // ColorScheme configuration and 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,
    )
}
Copy the code

Now, on Android 12 and later, Jetchat’s interface automatically adjusts colors based on the user’s wallpaper, providing a beautiful experience for both light and dark themes.

△ Dynamic color matching for dark and light themes

typography

Now that we know the color scheme, let’s look at typography. Material Design 3 has new font specifications, including text styles adapted from Material Design 2. Naming and grouping of styles is simplified to display, headings, headings, body, and labels; Each group has large, medium and small fonts.

△ Grouping of Material 3 and Material 2 font styles

Compose uses the new Typography class to model the font specification, whose parameters are named after styles in the Material Design 3 font specification. We can create an instance of Typography using the Roboto reference value, override the default value with a custom text style, and finally pass Typography as a parameter to the MaterialTheme.

import androidx.compose.material3.Typography
 
class Typography (
    val displayLarge: TextStyle,
    val displayMedium: TextStyle,
    val displaySmall: TextStyle,
    // headlineLarge, titleMedium, bodySmall, etc
)
 
valAppTypography = Typography ( bodyLarge = TextStyle(...) .// displayLarge, titleMedium, labelSmall, etc
    // Use the default Roboto reference value
)
 
MaterialTheme (
    typography = AppTypography,
    // colorScheme
) {
    //App content
}
Copy the code

Let’s take a look at Jetchat’s typography. The designers gave us a new brand font specification, using the custom Montserrat and Karla fonts:

△ Font size used by Jetchat

We first declare these fonts using the FontFamily class, which will hold instances of the Font class. We can construct the Font class using the Font resource ID and Font thickness, then declare the Jetchat Font style using the Typography class, and use the TextStyle class to override each TextStyle, including our Font, size, Font thickness, and other typographical values. Finally, again, pass Typography as a parameter to the 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, etc
)
 
MaterialTheme (
    typography = JetchatTypography,
    / / colorScheme, content
)
Copy the code

Let’s take a look at the Jetchat chat interface, where each part of the interface uses a different text style from the Jetchat font specification. For example, contacts and timestamps in messages use titleMedium and labelSmall styles, respectively. They access the theme font value through the MaterialTheme. Typography representation.

▽ Font setting for the chat screen

@Composable
fun Message(...).{... Text (style = MaterialTheme.typography.titleMedium, ...) ... Text (style = MaterialTheme.typography.labelSmall, ...) }Copy the code

highly

Now that we know about the Material 3 theme related updates, let’s look at another key Material Design update — height. In summary, Material 2 uses shadows to represent height, while Material 3 uses a tonal color overlay to represent height. This is a new way to differentiate between containers and surfaces, and increasing the height of the tone makes the tone more prominent.

The height overlay is part of the dark theme in Material 2 and has been changed to a tonal color overlay in Material 3.

△ Comparison between M2 and M3 height system effect

Take the Surface component as an example. Surface is a composable that supports most Material components. The existing Surface composable implements Material Design 2’s height system. In Material Design 2, the Surface receives an elevation parameter and handles shadows and overlay rendering in a dark theme. We have introduced a new version of the Surface for Material Design 3, which accepts a tonalElevation parameter and handles color overlay rendering in both light and dark themes. Let’s look at the differences:

△ Surface in Material 2

△ Surface in Material 3

Component updates

Material 3 has updated many components, such as buttons, application bars, dialogs, FAB, and navigation components. This type of update takes advantage of the new Material 3 theme setting values and includes the latest updates to each component 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. In Material 3 this composable was renamed NavigationBar, which conforms to the Material Design 3 specification, where the parameters were changed to containerColor and tonalElevation to more accurately reflect their respective uses.

// NavigationBar in Materail 2
import androidx.compose.material.BottomNavigation
 
@Composable
fun BottomNavigation (
    // M2 Default value
    backgroundColor: Color, 
    elevation: Dp,...).
 
 
// NavigationBar in Materail 3
import androidx.compose.material3.NavigationBar
 
@Composable
fun NavigationBar (
    // M3 default value
    containerColor: Color, 
    tonalElevation: Dp,...).
Copy the code

△ Style changes before and after the update

The components in Compose Material 3 have been updated a number of times, and to give you a complete picture of all the components and how they are implemented, we have updated the Compose Material Catalog application with a new Material 3 section. Check out the source code on AOSP and download the app on Google Play.

Let’s take a look at an example from Jetchat. There is an extended FAB component for composing messages on the profile interface, which has been updated from Material 2 to Material 3. This is the Material of version 2 is a simple implementation, using the ExtendedFloatingActionButton items which are combined and used within the Icon and Text, can be combined and 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,
    ...
)
Copy the code

The Material 3 update to this component is shown here, and the dependency import for the composable item has been changed to Material 3, using 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,
    ...
)
Copy the code

Visual effect

Some aspects of Material You come from the new Android 12 visual style and system interface, and two of the major changes are the ripple and scroll effects. Ripple effect now uses a tiny flash to illuminate the surface when pressed, and Scroll effect uses a stretch effect on the edges of the scroll container. No additional work is required to implement these changes, and stretch scrolling is turned on by default in the Composable component of the scroll container in Compose Foundation 1.1 and later versions; The flash ripple available on Android 12 works with all Material components.

△ Ripple effect in M2 and M3

// Stretch scroll // works with LazyColumn, Lazy Row, LazyVerticalGrid, etc // ComposeFoundation 1.1.0+ works with flash ripple // works with all Material 2 and Material 3 Component // Android 12+ is availableCopy the code

Interoperability improvements with Android View

Interoperability with Android views is an important part of developing an application with Compose, and we’ve made some updates in Material 3 to support this. The MDC-AndroidCompose Theme Adapter library is a Material component that enables you to reuse Android XML themes for easy Theme setup in Jetpack Compose.

The existing MdcTheme composable is compatible with the Material 2 XML theme, and we have also introduced a new Mdc3Theme composable that is compatible with the Material 3 XML theme.

The MDC-Androidcompose Theme Adapter is the bridge between the XML Theme and the MaterialTheme

The end of the

It’s a good time to try out Compose Material 3 in your Android app, and we’ve prepared a series of resources to help you navigate your journey. We’ve provided the new Compose Material 3 API documentation and a new Empty Compose Activity template in Android Studio that contains updates for Material 3. In addition, we’ve updated the Topic setup guide in Compose, as well as the Jetchat example and Compose Material Catalog application we saw earlier, and the MDC-Android ComposeTheme Adapter interoperability library.