Material Design 3 в Compose

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

Ниже мы демонстрируем реализацию Material Design 3 на примере приложения «Ответ» . Пример ответа полностью основан на 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
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppComposable() {
    // M3 composables
}

Тематика материалов

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

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

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

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

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

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

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

Пример цветовой схемы подсветки приложения для ответа
Рисунок 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 , передайте ее в MaterialTheme M3:

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
)

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

Формы

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

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

Определение фигур

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 , вы можете передать их в MaterialTheme M3:

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

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

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

Вы можете прочитать больше о рекомендациях Material по применению формы .

Акцент

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

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

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

Высота

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

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

Наложения возвышений в темных темах также изменились на наложения тональных цветов в Материале 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 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 . Ответная витрина постоянного ящика навигации

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

Подробнее о настройке Материала 3 можно прочитать.

Системный интерфейс

Некоторые аспекты Material You взяты из нового визуального стиля и системного пользовательского интерфейса на Android 12 и более поздних версиях. Двумя ключевыми областями, где происходят изменения, являются пульсация и чрезмерная прокрутка. Для реализации этих изменений не требуется никаких дополнительных действий.

Пульсация

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

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

Прокрутка

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

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

Доступность

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

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

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

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

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

Все компоненты 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
    )
) {
}

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

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

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

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

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

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

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

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

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

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

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

Документы

Ссылка на API и исходный код

Видео

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