Переход с 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")

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

В версии 1.6.0 библиотеки Wear Compose Foundation были добавлены новые компоненты, предназначенные для работы с компонентами 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")
implementation("androidx.wear.compose:compose-navigation:1.6.0")

Тема

В версиях 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.5 и включает в себя следующие особенности:

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

Стили текста

В 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.5. Количество параметров формы увеличилось, они имеют другие названия и по-другому сопоставляются с компонентами 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 Expressive для Wear OS.

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

Материал 3 Эквивалентный компонент материала 2.5 (если он не является новым в M3)
androidx.wear.compose.material3.AlertDialog androidx.wear.compose.material.dialog.Alert
androidx.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
androidx.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
androidx.wear.compose.foundation.hierarchicalFocusGroup Используется для аннотирования элементов композиции в приложении, отслеживания активной части композиции и координации фокуса.
androidx.wear.compose.foundation.pager.HorizontalPager Горизонтально прокручиваемая пейджерная панель, созданная на основе компонентов Compose Foundation с улучшениями, разработанными специально для Wear OS, для повышения производительности и соответствия рекомендациям Wear OS.
androidx.wear.compose.foundation.pager.VerticalPager Вертикально прокручиваемая пейджерная панель, созданная на основе компонентов Compose Foundation с улучшениями, разработанными специально для Wear OS, для повышения производительности и соответствия рекомендациям Wear OS.
androidx.wear.compose.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 в качестве конечного элемента списка. См. следующий код, чтобы узнать, как использовать 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 на TransformingLazyColumn

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

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

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

Чтобы убедиться в правильности отступов вверху и внизу списка, используйте модификатор minimumVerticalContentPadding .

val columnState = rememberTransformingLazyColumnState()
val transformationSpec = rememberTransformationSpec()
ScreenScaffold(
    scrollState = columnState
) { contentPadding ->
    TransformingLazyColumn(
        state = columnState,
        contentPadding = contentPadding
    ) {
        item {
            ListHeader(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ListHeaderDefaults.minimumTopListContentPadding),
                transformation = SurfaceTransformation(transformationSpec)
            ) {
                Text(text = "Header")
            }
        }
        // ... other items
        item {
            Button(
                modifier = Modifier
                    .fillMaxWidth()
                    .transformedHeight(this, transformationSpec)
                    .minimumVerticalContentPadding(ButtonDefaults.minimumVerticalListContentPadding),
                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 и исходный код

Дизайн