Темы и цвета Material 3
Разбираемся, как Material 3 задаёт единые цвета, шрифты и формы через MaterialTheme.
MaterialTheme — composable, который раздаёт всем вложенным элементам общую цветовую схему, типографику и формы.
Единый источник стиля
Вместо того чтобы прописывать цвета у каждого Text и Button, вы задаёте тему один раз наверху. Компоненты Material сами берут из неё нужные значения:
@Composable
fun App() {
MaterialTheme {
Surface {
Text("Текст в цветах темы")
}
}
}Surface здесь — фоновая «подложка», которая красит область цветом темы и задаёт уровень над фоном. Доступ к текущим значениям темы — через объект MaterialTheme:
Text(
text = "Заголовок",
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.headlineMedium
)Цветовые роли, а не конкретные цвета
Material 3 оперирует ролями: primary (основной), secondary, background, surface, error и парные к ним onPrimary, onBackground (цвет текста поверх). Вы используете роль, а конкретный оттенок подставляет тема. Поэтому переключение на тёмную тему не требует переписывать каждый экран.
| Роль | Где применяется |
primary | акцентные элементы, основные кнопки |
background | фон экрана |
surface | фон карточек и панелей |
onPrimary | текст/иконки поверх primary |
Светлая и тёмная тема
Тему собирают из двух цветовых схем — светлой и тёмной — и выбирают нужную по системной настройке:
@Composable
fun AppTheme(content: @Composable () -> Unit) {
val colors = if (isSystemInDarkTheme()) darkColorScheme() else lightColorScheme()
MaterialTheme(colorScheme = colors, content = content)
}Как работает под капотом
MaterialTheme кладёт цвета, шрифты и формы в особый механизм Compose — CompositionLocal. Это «неявный контекст», доступный всем вложенным composable без передачи через параметры. Когда Text запрашивает MaterialTheme.colorScheme.primary, он читает ближайшее значение из этого контекста. Смена темы наверху автоматически перерисует всё, что эти значения читало.
Частые ошибки
- Прописывать жёсткие цвета (
Color(0xFF...)) вместо ролей — тёмная тема ломается. - Использовать
primaryдля текста на нём же — нужен парныйonPrimary, иначе текст сольётся с фоном. - Забыть обернуть приложение в
MaterialTheme— компоненты получат значения по умолчанию.
Итог
MaterialThemeзадаёт цвета, шрифты и формы один раз для всего дерева.- Используйте цветовые роли (
primary,surface,onPrimary), а не конкретные оттенки. - Светлая и тёмная темы — это две схемы, выбираемые по системной настройке.