Material Design 3 в Compose

Jetpack Compose предлагает реализацию Material You и Material 3 Expressive , следующего поколения Material Design. M3 Expressive — это расширение Material Design 3, включающее в себя основанные на исследованиях обновления тем, компонентов, движения, типографики и многого другого — все это разработано, чтобы помочь вам создавать привлекательные и желанные продукты, которые нравятся пользователям. Он также поддерживает функции персонализации Material You, такие как динамический цвет. M3 Expressive дополняет визуальный стиль Android 16 и системный пользовательский интерфейс.

Ниже мы демонстрируем реализацию Material Design 3 на примере приложения Reply . Пример Reply полностью основан на Material Design 3.

Ответить на пример приложения с использованием Material Design 3
Рисунок 1. Пример приложения Reply с использованием Material Design 3

Зависимость

Чтобы начать использовать Material 3 в приложении Compose, добавьте зависимость Compose Material 3 в файлы build.gradle :

implementation "androidx.compose.material3:material3:$material3_version"

После добавления зависимости вы можете начать добавлять в свои приложения системы Material Design, включая цвет, типографику и форму.

Экспериментальные API

Некоторые API M3 считаются экспериментальными. В таких случаях вам необходимо включить их на уровне функции или файла, используя аннотацию ExperimentalMaterial3Api :

// import androidx.compose.material3.ExperimentalMaterial3Api
@Composable
fun AppComposable() {
    // M3 composables
}

Материальная тематика

Тема M3 содержит следующие подсистемы: цветовая схема , типографика и формы . Когда вы настраиваете эти значения, ваши изменения автоматически отражаются в компонентах M3, которые вы используете для создания своего приложения.

Подсистемы материального дизайна: цвет, типографика и формы
Рисунок 2. Подсистемы материального дизайна: цвет, типографика и формы

Jetpack Compose реализует эти концепции с помощью компонуемого M3 MaterialTheme :

MaterialTheme(
    colorScheme = /* ...
    typography = /* ...
    shapes = /* ...
) {
    // M3 app content
}

Чтобы тематически оформить содержимое вашего приложения, определите цветовую схему, типографику и формы, характерные для вашего приложения.

Цветовая схема

Основой цветовой схемы является набор из пяти ключевых цветов. Каждый из этих цветов относится к тональной палитре из 13 тонов, которые используются компонентами Material 3. Например, это цветовая схема для светлой темы для Reply :

Ответить на пример цветовой схемы освещения приложения
Рисунок 3. Ответить на пример цветовой схемы подсветки приложения

Подробнее о цветовой схеме и ролях цветов .

Генерация цветовых схем

Хотя вы можете создать собственную 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, в которой алгоритм извлекает пользовательские цвета из обоев пользователя для применения к его приложениям и системному пользовательскому интерфейсу. Эта цветовая палитра используется в качестве отправной точки для создания светлых и темных цветовых схем.

Ответить пример динамической темы приложения из обоев (слева) и темы приложения по умолчанию (справа)
Рисунок 4. Пример динамической темы приложения «Ответить» из обоев (слева) и темы приложения по умолчанию (справа)

Динамический цвет доступен на 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
}

Использование цвета

Вы можете получить доступ к цветам темы Material в своем приложении через MaterialTheme.colorScheme :

Text(
    text = "Hello theming",
    color = MaterialTheme.colorScheme.primary
)

Каждая цветовая роль может использоваться в различных местах в зависимости от состояния компонента, его значимости и акцента.

  • Основной — это базовый цвет, используемый для основных компонентов, таких как выступающие кнопки, активные состояния и оттенок выступающих поверхностей.
  • Вторичный ключевой цвет используется для менее заметных компонентов пользовательского интерфейса, таких как фильтры, и расширяет возможности цветового выражения.
  • Третичный ключевой цвет используется для определения роли контрастных акцентов, которые можно использовать для уравновешивания основных и дополнительных цветов или привлечения повышенного внимания к элементу.

В дизайне примера приложения Reply используется цвет основного контейнера поверх основного контейнера, чтобы выделить выбранный элемент.

Основной контейнер и текстовые поля с цветом основного контейнера.
Рисунок 5. Основной контейнер и текстовые поля с цветом основного контейнера.

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,
    )
}

Здесь в панели навигации по ответам вы можете увидеть, как вторичные и третичные цвета контейнеров используются в контрасте для создания акцента и акцента.

Комбинация третичного контейнера и третичного контейнера для кнопки плавающего действия.
Рисунок 6. Комбинация третичного контейнера и третичного контейнера для кнопки плавающего действия.

Типографика

Material Design 3 определяет масштаб шрифтов , включая стили текста, адаптированные из Material Design 2. Наименование и группировка были упрощены до: отображение, заголовок, название, основной текст и метка, с большим, средним и малым размером для каждого.

Масштаб типографики по умолчанию для Material design 3
Рисунок 7. Масштаб типографики по умолчанию для Material Design 3
М3 Размер шрифта/Высота строки по умолчанию
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
    ),
    // ..
)
// ..

Корпус большой, корпус средний и этикетка средняя для различного типографского использования.
Рисунок 8. Большой корпус, средний корпус и средняя этикетка для различного использования в типографике.

Вашему продукту, скорее всего, не понадобятся все 15 стилей по умолчанию из шкалы типов Material Design. В этом примере для сокращенного набора выбрано пять размеров, а остальные опущены.

Вы можете настроить типографику, изменив значения по умолчанию 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
}

Использовать стили текста

Вы можете получить типографику, предоставленную для компоновки M3 MaterialTheme , с помощью MaterialTheme.typography :

Text(
    text = "Hello M3 theming",
    style = MaterialTheme.typography.titleLarge
)
Text(
    text = "you are learning typography",
    style = MaterialTheme.typography.bodyMedium
)

Подробнее о рекомендациях Material по применению типографики можно прочитать здесь.

Формы

Материальные поверхности могут быть представлены в различных формах. Формы направляют внимание, идентифицируют компоненты, сообщают о состоянии и выражают бренд.

Шкала форм определяет стиль углов контейнера, предлагая диапазон скруглений от квадратного до полностью круглого.

Определить формы

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 */
}

Средняя форма для карточки и большая форма для плавающей кнопки действия в примере приложения «Ответить».
Рисунок 9. Средняя форма для карточки и большая форма для плавающей кнопки действия в примере приложения «Ответить»

Есть еще две фигуры — RectangleShape и CircleShape — которые являются частью Compose. Прямоугольная фигура не имеет радиуса границы, а круглая фигура показывает полностью закругленные края:

Card(shape = RectangleShape) { /* card content */ }
Card(shape = CircleShape) { /* card content */ }

В примерах ниже показаны некоторые компоненты с примененными к ним значениями формы по умолчанию:

Значения форм по умолчанию для всех компонентов Material 3.
Рисунок 10. Значения форм по умолчанию для всех компонентов Material 3.

Подробнее о рекомендациях по применению формы можно прочитать в разделе «Материалы».

Акцент

Выделение в M3 обеспечивается с помощью вариаций цвета и его цветовых комбинаций. В M3 есть два способа добавить акцент вашему пользовательскому интерфейсу:

  • Использование поверхности, варианта поверхности и фона вместе с цветами на поверхности, на поверхности-варианты из расширенной цветовой системы M3. Например, поверхность может использоваться с вариантом на поверхности, а вариант поверхности может использоваться с на поверхности для обеспечения различных уровней акцента.
Использование нейтральных цветовых сочетаний для акцентирования внимания.
Рисунок 11. Использование нейтральных цветовых сочетаний для акцентирования внимания.
  • Использование различных толщин шрифта для текста. Выше вы видели, что вы можете задать пользовательские толщины для нашей шкалы шрифтов для обеспечения различной выразительности.

bodyLarge = TextStyle(
    fontWeight = FontWeight.Bold
),
bodyMedium = TextStyle(
    fontWeight = FontWeight.Normal
)

Высота

Материал 3 представляет возвышение в основном с использованием тональных цветовых наложений. Это новый способ дифференцировать контейнеры и поверхности друг от друга — увеличение тонального возвышения использует более заметный тон — в дополнение к теням.

Тональное возвышение с теневым возвышением
Рисунок 12. Тональное возвышение с теневым возвышениемE

Наложения рельефа в темных темах также были изменены на тональные цветовые наложения в Material 3. Цвет наложения берется из слота основного цвета.

Возвышение тени против возвышения тона в Material Design 3
Рисунок 13. Возвышение тени против возвышения тона в Material Design 3

Поверхность M3 — основа, которую можно использовать для большинства компонентов M3 — поддерживает как тональное, так и теневое возвышение:

Surface(
    modifier = Modifier,
    tonalElevation = /*...
    shadowElevation = /*...
) {
    Column(content = content)
}

Материальные компоненты

Material Design поставляется с богатым набором компонентов Material (таких как кнопки, фишки, карты, панель навигации), которые уже следуют Material Theming и помогают вам создавать красивые приложения Material Design. Вы можете начать использовать компоненты со свойствами по умолчанию прямо из коробки.

Button(onClick = { /*..*/ }) {
    Text(text = "My Button")
}

M3 предоставляет множество версий одних и тех же компонентов для использования в различных ролях в зависимости от акцента и внимания.

Выделение кнопок от FAB, Primary вниз до кнопки Text
Рисунок 14. Выделение кнопки от FAB, Primary вниз к кнопке Text
  • Расширенная плавающая кнопка действия для наиболее важного действия:

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 = { }
        )
    }
}

Ответить Демонстрация BottomNavigationBar (слева) и NavigationRail (справа)
Рисунок 15. Ответить на демонстрацию BottomNavigationBar (слева) и NavigationRail (справа)

Ответьте, используя обе темы по умолчанию, чтобы обеспечить захватывающий пользовательский опыт для устройств всех размеров.

NavigationDrawer используется для планшетов среднего и большого размера, где достаточно места для отображения деталей. Вы можете использовать как PermanentNavigationDrawer , так и ModalNavigationDrawer вместе с NavigationRail .

PermanentNavigationDrawer(modifier = Modifier.fillMaxHeight(), drawerContent = {
    Destinations.entries.forEach { replyDestination ->
        NavigationRailItem(
            selected = selectedDestination == replyDestination,
            onClick = { },
            icon = { },
            label = { }
        )
    }
}) {
}

Ответить Витрина постоянного навигационного ящика
Рисунок 16. Ответная витрина постоянного навигационного ящика

Параметры навигации улучшают пользовательский опыт, эргономику и доступность. Вы можете узнать больше о компонентах навигации Material в адаптивной кодовой лаборатории Compose .

Настройте тему компонента

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 и выше. Две ключевые области, где есть изменения, — это рябь и прокрутка. Для внедрения этих изменений не требуется дополнительных усилий.

Рябь

Ripple теперь использует едва заметный блеск для подсветки поверхностей при нажатии. Compose Material Ripple использует платформу RippleDrawable под капотом на Android, поэтому sparkle ripple доступен на Android 12 и выше для всех компонентов Material.

Пульсация в M2 против M3
Рисунок 17. Пульсация в M2 по сравнению с M3

Оверскролл

Overscroll теперь использует эффект растяжения на краю прокручиваемых контейнеров. Растягивание overscroll включено по умолчанию в прокручиваемых контейнерах-компоновщиках — например, LazyColumn , LazyRow и LazyVerticalGrid — в Compose Foundation 1.1.0 и выше, независимо от уровня API.

Прокрутка с использованием эффекта растяжения по краю контейнера
Рисунок 18. Прокрутка с использованием эффекта растяжения по краю контейнера

Доступность

Стандарты доступности, встроенные в компоненты Material, призваны обеспечить основу для инклюзивного дизайна продукта. Понимание доступности вашего продукта может повысить удобство использования для всех пользователей, включая людей с плохим зрением, слепотой, нарушениями слуха, когнитивными нарушениями, двигательными нарушениями или ситуативными нарушениями (например, сломанной рукой).

Доступность цвета

Динамический цвет разработан для соответствия стандартам доступности для цветового контраста. Система тональных палитр имеет решающее значение для того, чтобы сделать любую цветовую схему доступной по умолчанию.

Цветовая система Material предоставляет стандартные значения тонов и измерения, которые можно использовать для достижения доступных коэффициентов контрастности.

Пример ответа: Первичная, вторичная и третичная тональные палитры (сверху вниз)
Рисунок 19. Пример приложения «Ответ»: первичная, вторичная и третичная тональные палитры (сверху вниз)

Все компоненты Material и динамическое оформление уже используют указанные выше цветовые роли из набора тональных палитр , выбранных для соответствия требованиям доступности. Однако, если вы настраиваете компоненты, обязательно используйте соответствующие цветовые роли и избегайте несоответствий.

Используйте on-primary поверх primary и on-primary-container поверх 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
    )
) {
}

Достаточный контраст (слева) против плохого контраста (справа)
Рисунок 20. Достаточный контраст (слева) против плохого контраста (справа)

Доступность типографики

Шкала типов M3 обновляет статическую шкалу типов и значений, предлагая упрощенную, но динамичную структуру категорий размеров, масштабируемых на разных устройствах.

Например, в M3 параметру Display Small можно назначать разные значения в зависимости от контекста устройства, например, телефона или планшета.

Большие экраны

В материале содержатся рекомендации по адаптивным макетам и складным устройствам, которые сделают ваши приложения доступными и улучшат эргономику для пользователей, использующих большие устройства.

Material предоставляет различные виды навигации , помогающие обеспечить лучший пользовательский опыт на больших устройствах.

Вы можете узнать больше о рекомендациях по обеспечению качества приложений для Android с большим экраном и ознакомиться с нашим примером ответа для адаптивного и доступного дизайна.

Узнать больше

Чтобы узнать больше о Material Theming в Compose, ознакомьтесь со следующими ресурсами:

Примеры приложений

Документы

Справочник API и исходный код

Видео

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}