Переход с Material 2.5 на Material 3 в Compose для Wear OS

Material 3 Expressive — это следующий этап развития Material Design. Он включает в себя обновленные темы оформления, компоненты и функции персонализации, такие как динамическая цветокоррекция.

Данное руководство посвящено миграции приложений с библиотеки Jetpack Wear Compose Material 2.5 (androidx.wear.compose) на библиотеку Jetpack Wear Compose Material 3 (androidx.wear.compose.material3) .

Подходы

Для миграции кода вашего приложения с M2.5 на M3 следуйте тому же подходу, что описан в руководстве по миграции телефонов Compose Material , в частности:

Зависимости

M3 имеет отдельный пакет и версию, отличную от M2.5:

М2.5

implementation("androidx.wear.compose:compose-material:1.4.0")

М3

implementation("androidx.wear.compose:compose-material3:1.6.0-alpha07")

Последние версии M3 можно найти на странице релизов Wear Compose Material 3 .

В версии библиотеки Wear Compose Foundation 1.6.0-alpha07 появились новые компоненты, разработанные для работы с компонентами Material 3. Аналогично, SwipeDismissableNavHost из библиотеки Wear Compose Navigation получил обновлённую анимацию при работе на Wear OS 6 (уровень API 36) или выше. При обновлении до версии Wear Compose Material 3 мы рекомендуем также обновить библиотеки Wear Compose Foundation и Navigation:

implementation("androidx.wear.compose:compose-foundation:1.6.0-alpha07")
implementation("androidx.wear.compose:compose-navigation:1.6.0-alpha07")

Тема

В версиях M2.5 и M3 компонуемый элемент темы называется MaterialTheme , но пакеты импорта и параметры различаются. В версии M3 параметр Colors был переименован в ColorScheme , а для реализации переходов был введен MotionScheme .

М2.5

import androidx.wear.compose.material.MaterialTheme

MaterialTheme(
    colors = AppColors,
    typography = AppTypography,
    shapes = AppShapes,
    content = content
)

М3

import androidx.wear.compose.material3.MaterialTheme
// ...
    MaterialTheme(
        colorScheme = ColorScheme(),
        typography = Typography(),
        shapes = Shapes(),
        motionScheme = MotionScheme.standard(),
        content = { /*content here*/ }
    )

Цвет

Цветовая система в M3 значительно отличается от M2.5. Количество цветовых параметров увеличилось, у них другие имена, и они по-разному сопоставляются с компонентами M3. В Compose это относится к классу Colors из M2.5, классу ColorScheme из M3 и связанным с ними функциям:

М2.5

import androidx.wear.compose.material.Colors

val appColorScheme: Colors = Colors(
   // M2.5 Color parameters
)

М3

import androidx.wear.compose.material3.ColorScheme
// ...
    val appColorScheme: ColorScheme = ColorScheme(
        // M3 ColorScheme parameters
    )

В следующей таблице описаны основные различия между M2.5 и M3:

М2.5

М3

Color

переименован в ColorScheme

13 цветов

28 цветов

Н/Д

новая динамическая цветовая тема

Н/Д

новые третичные цвета для большей выразительности

Динамическое цветовое оформление

Новая функция в M3 — динамическое изменение цветовой гаммы . Если пользователи меняют цвет циферблата, цвета в пользовательском интерфейсе также меняются в соответствии с ним.

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

@Composable
fun myApp() {
    val dynamicColorScheme = dynamicColorScheme(LocalContext.current)
    MaterialTheme(colorScheme = dynamicColorScheme ?: myBrandColors) {}
}

internal val myBrandColors: ColorScheme = ColorScheme( /* Specify colors here */)

Типография

Система типографики в M3 отличается от M2 и включает в себя следующие особенности:

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

М2.5

import androidx.wear.compose.material.Typography

val Typography = Typography(
   // M2.5 TextStyle parameters
)

М3

import androidx.wear.compose.material3.Typography

val Typography = Typography(
    // M3 TextStyle parameters
)

Flex Fonts

Функция Flex Fonts позволяет дизайнерам задавать ширину и толщину шрифта для конкретных размеров.

Стили текста

В M3 доступны следующие стили текста . Они используются по умолчанию различными компонентами M3.

Типография

Стиль текста

Отображать

displayLarge, displayMedium, displaySmall

Заголовок

titleLarge, titleMedium, titleSmall

Этикетка

labelLarge, labelMedium, labelSmall

Тело

bodyLarge, bodyMedium, bodySmall, bodyExtraSmall

Цифра

numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall

Дуга

arcLarge, arcMedium, arcSmall

Форма

Система форм в M3 отличается от M2. Количество параметров формы увеличилось, они имеют другие названия и по-другому сопоставляются с компонентами M3. Доступны следующие размеры форм:

  • Очень маленький
  • Маленький
  • Середина
  • Большой
  • Очень большой

В Compose это относится к классам M2 Shapes и M3 Shapes :

М2.5

import androidx.wear.compose.material.Shapes

val Shapes = Shapes(
   // M2.5 Shapes parameters
)

М3

import androidx.wear.compose.material3.Shapes

val Shapes = Shapes(
    // M3 Shapes parameters
)

В качестве отправной точки используйте сопоставление параметров Shapes из модуля "Перенос из Material 2 в Material 3" в Compose .

Изменение формы

В M3 представлена ​​функция изменения формы: теперь формы меняются в ответ на взаимодействия.

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

Кнопки

Функция изменения формы

IconButton

Метод IconButtonDefaults.animatedShape() анимирует кнопку-значок при нажатии.

IconToggleButton

Метод IconToggleButtonDefaults.animatedShape() анимирует кнопку переключения значка при нажатии и

Метод IconToggleButtonDefaults.variantAnimatedShapes() анимирует кнопку переключения значка при нажатии и при установке/снятии флажка.

TextButton

Метод TextButtonDefaults.animatedShape() анимирует текстовую кнопку при нажатии.

TextToggleButton

Метод TextToggleButtonDefaults.animatedShapes() анимирует переключение текста при нажатии, а метод TextToggleButtonDefaults.variantAnimatedShapes() анимирует переключение текста при нажатии и установке/снятии флажка.

Компоненты и компоновка

Большинство компонентов и схем из M2.5 доступны в M3. Однако некоторые компоненты и схемы из M3 отсутствовали в M2.5. Кроме того, некоторые компоненты M3 имеют больше вариантов, чем их аналоги в M2.5.

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

Материал 2.5

Материал 3

androidx.wear.compose.material.dialog.Alert

androidx.wear.compose.material3.AlertDialog

androidx.wear.compose.material.Button

androidx.wear.compose.material3.IconButton или androidx.wear.compose.material3.TextButton

androidx.wear.compose.material.Card

androidx.wear.compose.material3.Card

androidx.wear.compose.material.TitleCard

androidx.wear.compose.material3.TitleCard

androidx.wear.compose.material.AppCard

androidx.wear.compose.material3.AppCard

androidx.wear.compose.material.Checkbox

Нет эквивалента в M3, перейдите на androidx.wear.compose.material3.CheckboxButton или androidx.wear.compose.material3.SplitCheckboxButton .

androidx.wear.compose.material.Chip

androidx.wear.compose.material3.Button или
androidx.wear.compose.material3.OutlinedButton или
androidx.wear.compose.material3.FilledTonalButton или
androidx.wear.compose.material3.ChildButton

androidx.wear.compose.material.CompactChip

androidx.wear.compose.material3.CompactButton

androidx.wear.compose.material.InlineSlider

androidx.wear.compose.material3.Slider

androidx.wear.compose.material.LocalContentAlpha

Удалено, поскольку не используется Text или Icon в ​​Material 3.

androidx.wear.compose.material.PositionIndicator

androidx.wear.compose.material3.ScrollIndicator

androidx.wear.compose.material.RadioButton

Нет эквивалента в M3, перейдите на androidx.wear.compose.material3.RadioButton или androidx.wear.compose.material3.SplitRadioButton.

androidx.wear.compose.material.SwipeToRevealCard

androidx.wear.compose.material3.SwipeToReveal

androidx.wear.compose.material.SwipeToRevealChip

androidx.wear.compose.material3.SwipeToReveal

android.wear.compose.material.Scaffold

androidx.wear.compose material3.AppScaffold и androidx.wear.compose.material3.ScreenScaffold

androidx.wear.compose.material.SplitToggleChip

Нет эквивалента в M3, перейдите на androidx.wear.compose.material3.SplitCheckboxButton , androidx.wear.compose.material3.SplitSwitchButton или androidx.wear.compose.material3.SplitRadioButton.

androidx.wear.compose.material.Switch

Нет эквивалента в M3, перейдите на androidx.wear.compose.material3.SwitchButton или androidx.wear.compose.material3.SplitSwitchButton.

androidx.wear.compose.material.ToggleButton

androidx.wear.compose.material3.IconToggleButton или androidx.wear.compose.material3.TextToggleButton

androidx.wear.compose.material.ToggleChip

androidx.wear.compose.material3.CheckboxButton или
androidx.wear.compose.material3.RadioButton или
androidx.wear.compose.material3.SwitchButton

androidx.wear.compose.material.Vignette

Удалено как не включенное в выразительный дизайн Material 3 для Wear OS.

Вот полный список всех компонентов Material 3:

Материал 3

Эквивалентный компонент материала 2.5 (если он не является новым в M3)

androidx.wear.compose.material3.AlertDialog

androidx.wear.compose.material.dialog.Alert

androix.wear.compose.material3.AnimatedPage

Новый

androidx.wear.compose.material3.AnimatedText

Новый

androidx.wear.compose material3.AppScaffold

android.wear.compose.material.Scaffold (with androidx.wear.compose.material3.ScreenScaffold )

androidx.wear.compose.material3.Button

androidx.wear.compose.material.Chip

androidx.wear.compose.material3.ButtonGroup

Новый

androidx.wear.compose.material3.Card

androidx.wear.compose.material.Card

androidx.wear.compose.material3.CheckboxButton

androidx.wear.compose.material.ToggleChip с элементом управления переключением по флажку

androidx.wear.compose.material3.ChildButton

androidx.wear.compose.material.Chip (только если фон не требуется)

androidx.wear.compose.material3.CircularProgressIndicator

androidx.wear.compose.material.CircularProgressIndicator

androidx.wear.compose.material3.CompactButton

androidx.wear.compose.material.CompactChip

androidx.wear.compose.material3.ConfirmationDialog

androidx.wear.compose.material.dialog.Confirmation

androidx.wear.compose.material3.curvedText

androidx.wear.compose.material.curvedText

androidx.wear.compose.material3.DatePicker

Новый

androidx.wear.compose.material3.Dialog

androidx.wear.compose.material.dialog.Dialog

androidx.wear.compose.material3.EdgeButton

Новый

androidx.wear.compose.material3.FadingExpandingLabel

Новый

androidx.wear.compose.material3.FilledTonalButton

androidx.wear.compose.material.Chip , когда требуется тональный фон кнопки.

androidx.wear.compose.material3.HorizontalPageIndicator

androidx.wear.compose.material.HorizontalPageIndicator

androidx.wear.compose.material3.HorizontalPagerScaffold

Новый

androidx.wear.compose.material3.Icon

androidx.wear.compose.material.Icon

androidx.wear.compose.material3.IconButton

androidx.wear.compose.material.Button

androidx.wear.compose.material3.IconToggleButton

androidx.wear.compose.material.ToggleButton

androidx.wear.compose.material3.LevelIndicator

Новый

androidx.wear.compose.material3.LinearProgressIndicator

Новый

androidx.wear.compose.material3.ListHeader

androidx.wear.compose.material.ListHeader

androidx.wear.compose.material3.ListSubHeader

Новый

androidx.wear.compose.material3.MaterialTheme

androidx.wear.compose.material.MaterialTheme

androidx.wear.compose.material3.OpenOnPhoneDialog

Новый

androidx.wear.compose.material3.Picker

androidx.wear.compose.material.Picker

androidx.wear.compose.material3.PickerGroup

androidx.wear.compose.material.PickerGroup

androix.wear.compose.material3.RadioButton

androidx.wear.compose.material.ToggleChip с переключателем-переключателем.

androidx.wear.compose.material3.ScreenScaffold

android.wear.compose.material.Scaffold (with androidx.wear.compose material3.AppScaffold )

androidx.wear.compose.material3.ScrollIndicator

androidx.wear.compose.material.PositionIndicator

androidx.wear.compose.material3.scrollaway

androidx.wear.compose.material.scrollaway

androidx.wear.compose.material3.SegmentedCircularProgressIndicator

Новый

androidx.wear.compose.material3.Slider

androidx.wear.compose.material.InlineSlider

androidx.wear.compose.material3.SplitRadioButton

androidx.wear.compose.material.SplitToggleChip

androidx.wear.compose.material3.SplitCheckboxButton

androidx.wear.compose.material.SplitToggleChip

androidx.wear.compose.material3.SplitSwitchButton

androidx.wear.compose.material.SplitToggleChip

androidx.wear.compose.material3.Stepper

androidx.wear.compose.material.Stepper

androidx.wear.compose.material3.SwipeToDismissBox

androidx.wear.compose.material.SwipeToDismissBox

androidx.wear.compose.material3.SwipeToReveal

androidx.wear.compose.material.SwipeToRevealCard и androidx.wear.compose.material.SwipeToRevealChip

androidx.wear.compose.material3.SwitchButton

androidx.wear.compose.material.ToggleChip с переключателем управления

androidx.wear.compose.material3.Text

androidx.wear.compose.material.Text

androidx.wear.compose.material3.TextButton

androidx.wear.compose.material.Button

androidx.wear.compose.material3.TextToggleButton

androidx.wear.compose.material.ToggleButton

androidx.wear.compose.material3.TimeText

androidx.wear.compose.material.TimeText

androidx.wear.compose.material3.VerticalPagerScaffold

Новый

И наконец, список некоторых важных компонентов из библиотеки Wear Compose Foundation:

Wear Compose Foundation 1.6.0-alpha07

androidx.wear.compose.foundation.hierarchicalFocusGroup

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

androidx.compose.foundation.pager.HorizontalPager

Горизонтально прокручиваемая пейджерная панель, созданная на основе компонентов Compose Foundation с улучшениями, разработанными специально для Wear OS, для повышения производительности и соответствия рекомендациям Wear OS.

androidx.compose.foundation.pager.VerticalPager

Вертикально прокручиваемая пейджерная панель, созданная на основе компонентов Compose Foundation с улучшениями, разработанными специально для Wear OS, для повышения производительности и соответствия рекомендациям Wear OS.

androidx.wear.foundation.lazy.TransformingLazyColumn

Может использоваться вместо ScalingLazyColumn для добавления эффектов трансформации при прокрутке к каждому элементу.

Кнопки

Кнопки в M3 отличаются от кнопок в M2.5. Чип M2.5 был заменен кнопкой. Реализация Button предоставляет значения по умолчанию для Text maxLines и textAlign . Эти значения по умолчанию можно переопределить в элементе Text .

М2.5

import androidx.wear.compose.material.Chip

//M2.5 Buttons
Chip(...)
CompactChip(...)
Button(...)

М3

//M3 Buttons
Button(onClick = { }){}
CompactButton(onClick = { }){}
IconButton(onClick = { }){}
TextButton(onClick = { }){}

В M3 также добавлены новые варианты кнопок. Ознакомьтесь с ними в справочном обзоре API Compose Material 3 .

В M3 представлена ​​новая кнопка: EdgeButton . EdgeButton доступна в 4 разных размерах: очень маленькая, маленькая, средняя и большая. В реализации EdgeButton предусмотрено значение по умолчанию для maxLines , зависящее от размера, которое можно настроить.

Если вы используете TransformingLazyColumn и ScalingLazyColumn , передайте EdgeButton в ScreenScaffold , чтобы он трансформировался, изменяя свою форму при прокрутке. См. следующий код, чтобы узнать, как использовать EdgeButton с ScreenScaffold и TransformingLazyColumn .

val state = rememberTransformingLazyColumnState()
ScreenScaffold(
    scrollState = state,
    contentPadding =
        rememberResponsiveColumnPadding(
            first = ColumnItemType.ListHeader
        ),
    edgeButton = {
        EdgeButton(
            onClick = { }
        ) {
            Text(stringResource(R.string.show))
        }
    }
){ contentPadding ->
    TransformingLazyColumn(state = state, contentPadding = contentPadding,){
        // additional code here
    }
}

Строительные леса

В M3 Scaffold отличается от M2.5. В M3 AppScaffold и новый компонент ScreenScaffold заменили Scaffold. AppScaffold и ScreenScaffold определяют структуру экрана и координируют переходы компонентов ScrollIndicator и TimeText .

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

Для Activity объявляется один AppScaffold , а для каждого Screen ScreenScaffold . AppScaffold добавляет на экраны компонент TimeText по умолчанию. При желании его можно переопределить, используя параметр timeText .

М2.5

import androidx.wear.compose.material.Scaffold

Scaffold {...}

М3

    AppScaffold {
        val navController = rememberSwipeDismissableNavController()
        SwipeDismissableNavHost(
            navController = navController,
            startDestination = "message_list"
        ) {
            composable("message_list") {
                MessageList(onMessageClick = { id ->
                    navController.navigate("message_detail/$id")
                })
            }
            composable("message_detail/{id}") {
                MessageDetail(id = it.arguments?.getString("id")!!)
            }
        }
    }
}

// Implementation of one of the screens in the navigation
@Composable
fun MessageDetail(id: String) {
    // .. Screen level content goes here
    val scrollState = rememberTransformingLazyColumnState()

    val padding = rememberResponsiveColumnPadding(
        first = ColumnItemType.BodyText
    )

    ScreenScaffold(
        scrollState = scrollState,
        contentPadding = padding
    ) { scaffoldPaddingValues ->
        // Screen content goes here
        // ...

Если вы используете HorizontalPager с HorizontalPagerIndicator , вы можете перейти на HorizontalPagerScaffold . HorizontalPagerScaffold размещается внутри AppScaffold . AppScaffold и HorizontalPagerScaffold определяют структуру Pager и координируют переходы компонентов HorizontalPageIndicator и TimeText .

По умолчанию HorizontalPagerScaffold отображает HorizontalPageIndicator в центре экрана и координирует отображение и скрытие TimeText и HorizontalPageIndicator в зависимости от того, осуществляется ли вызов Pager ; это определяется параметром PagerState .

Также появился новый компонент AnimatedPage , который анимирует страницу внутри Pager с эффектом масштабирования и затемнения в зависимости от ее положения.

AppScaffold {
    val pagerState = rememberPagerState(pageCount = { 10 })
    val columnState = rememberTransformingLazyColumnState()
    val contentPadding = rememberResponsiveColumnPadding(
        first = ColumnItemType.ListHeader,
        last = ColumnItemType.BodyText,
    )
    HorizontalPagerScaffold(pagerState = pagerState) {
        HorizontalPager(
            state = pagerState,
        ) { page ->
            AnimatedPage(pageIndex = page, pagerState = pagerState) {
                ScreenScaffold(
                    scrollState = columnState,
                    contentPadding = contentPadding
                ) { contentPadding ->
                    TransformingLazyColumn(
                        state = columnState,
                        contentPadding = contentPadding
                    ) {
                        item {
                            ListHeader(
                                modifier = Modifier.fillMaxWidth()
                            ) {
                                Text(text = "Pager sample")
                            }
                        }
                        item {
                            if (page == 0) {
                                Text(text = "Page #$page. Swipe right")
                            }
                            else{
                                Text(text = "Page #$page. Swipe left and right")
                            }
                        }
                    }
                }

            }
        }
    }
}

Наконец, M3 представляет VerticalPagerScaffold , который следует тому же принципу, что и HorizontalPagerScaffold :

AppScaffold {
    val pagerState = rememberPagerState(pageCount = { 10 })

    VerticalPagerScaffold(pagerState = pagerState) {
        VerticalPager(
            state = pagerState
        ) { page ->
            AnimatedPage(pageIndex = page, pagerState = pagerState) {
                ScreenScaffold {
                    ///…
                }
            }
        }
    }
}

Заполнитель

Между версиями M2.5 и M3 произошли некоторые изменения в API. Placeholder.PlaceholderDefaults теперь предоставляет два модификатора:

  • Modifier.placeholder , который отображается вместо еще не загруженного контента.
  • Modifier.placeholderShimmer эффекта мерцания-заполнителя. Модификатор `placeholderShimmer`, который обеспечивает эффект мерцания-заполнителя, воспроизводимый в цикле анимации в ожидании загрузки данных.

Дополнительные изменения в компоненте Placeholder приведены в таблице ниже.

М2.5

М3

PlaceholderState.startPlaceholderAnimation

Удалено

PlaceholderState.placeholderProgression

Удалено

PlaceholderState.isShowContent

Переименовано в !PlaceholderState.isVisible

PlaceholderState.isWipeOff

Удалено

PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush

удален

PlaceholderDefaults.placeholderBackgroundBrush

Удалено

PlaceholderDefaults.placeholderChipColors

Удалено

SwipeDismissableNavHost

SwipeDismissableNavHost является частью wear.compose.navigation . При использовании этого компонента с M3, MaterialTheme M3 обновляет значения LocalSwipeToDismissBackgroundScrimColor и LocalSwipeToDismissContentScrimColor .

TransformingLazyColumn

TransformingLazyColumn является частью пакета wear.compose.lazy.foundation и добавляет поддержку масштабирования и анимации изменения формы элементов списка при прокрутке, улучшая пользовательский опыт.

Аналогично ScalingLazyColumn , он предоставляет rememberTransformingLazyColumnState() для создания состояния TransformingLazyColumnState , которое запоминается при последующих композициях.

Для добавления анимации масштабирования и морфинга добавьте следующее к каждому элементу списка:

  • Для вычисления преобразованной высоты элементов с помощью TransformationSpec можно использовать Modifier.transformedHeight ; если вам не требуется дополнительная настройка, вы можете использовать rememberTransformationSpec() .
  • Преобразование SurfaceTransformation

val columnState = rememberTransformingLazyColumnState()
val contentPadding = rememberResponsiveColumnPadding(
    first = ColumnItemType.ListHeader,
    last = ColumnItemType.Button,
)
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState,
    contentPadding = contentPadding
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier.fillMaxWidth().transformedHeight(this, transformationSpec),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier.fillMaxWidth().transformedHeight(this, transformationSpec),
                transformation = SurfaceTransformation(transformationSpec),
                onClick = { /* ... */ },
                icon = {
                    Icon(
                        imageVector = Icons.Default.Build,
                        contentDescription = "build",
                    )
                },
            ) {
                Text(
                    text = "Build",
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
        }
    }
}

Чтобы узнать больше о миграции с версии M2.5 на M3 в Compose, обратитесь к следующим дополнительным ресурсам.

Образцы

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

Дизайн