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. Пример приложения «Ответить», использующего 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
)

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

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

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

Основной контейнер и текстовые поля с цветом основного контейнера.
Рисунок 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. Средняя форма для карточки и большая форма для плавающей кнопки действия в примере приложения «Ответить»

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

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. Тональное возвышение с теневым возвышением

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

Высота тени против высоты тона в Material Design 3
Рисунок 13. Подъем тени против тонального подъема в Material Design 3

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

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

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

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

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

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

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

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, поэтому эффект мерцания доступен на Android 12 и выше для всех компонентов Material.

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

Оверскролл

Эффект растяжения Overscroll теперь используется по краям прокручиваемых контейнеров. В составных элементах прокручиваемых контейнеров, например LazyColumn , LazyRow и LazyVerticalGrid , эффект растяжения Overscroll по умолчанию включен в Compose Foundation 1.1.0 и более поздних версиях, независимо от уровня API.

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

Доступность

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

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

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

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

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

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

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

Использование третичного контейнера поверх первичного дает пользователю плохую кнопку контрастности:

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

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

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

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

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

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

Документы

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

Видео

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