Как перейти с 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:

M2.5

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

M3

implementation("androidx.wear.compose:compose-material3:1.8.0-alpha01")

Последние версии M3 можно найти на странице выпусков Wear Compose.

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

implementation("androidx.wear.compose:compose-foundation:1.8.0-alpha01")
implementation("androidx.wear.compose:compose-navigation:1.8.0-alpha01")

Тема

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

M2.5

import androidx.wear.compose.material.MaterialTheme

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

M3

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

Цвет

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

M2.5

import androidx.wear.compose.material.Colors

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

M3

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

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

M2.5 M3
Colors Переименовано в ColorScheme.
13 цветов 29 цветов
Н/Д Новая динамическая цветовая тема
Н/Д Новые дополнительные цвета для более яркого оформления

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

Новая функция 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, в котором используются гибкие шрифты.

M2.5

import androidx.wear.compose.material.Typography

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

M3

import androidx.wear.compose.material3.Typography

val Typography = Typography(
    // M3 TextStyle parameters
)

Шрифты Flex

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

Стили текста

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

Параметры текста TextStyle
Экран displayLarge, displayMedium, displaySmall
Название titleLarge, titleMedium, titleSmall
Label (Звукозаписывающая компания) labelLarge, labelMedium, labelSmall
Текст bodyLarge, bodyMedium, bodySmall, bodyExtraSmall
Числительное numeralExtraLarge, numeralLarge, numeralMedium, numeralSmall, numeralExtraSmall
Дуга arcLarge, arcMedium, arcSmall

Фигура

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

  • Очень маленький
  • Мелкий
  • Средний
  • Крупный
  • Очень большой

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

M2.5

import androidx.wear.compose.material.Shapes

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

M3

import androidx.wear.compose.material3.Shapes

val Shapes = Shapes(
    // M3 Shapes parameters
)

Используйте сопоставление параметров фигур из статьи Переход с Material 2 на Material 3 в Compose в качестве отправной точки.

Морфинг фигур

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

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

Кнопки Функция преобразования фигур
IconButton IconButtonDefaults.animatedShapes анимирует кнопку со значком при нажатии.
IconToggleButton IconToggleButtonDefaults.animatedShapes анимирует кнопку переключения значков при нажатии, а
IconToggleButtonDefaults.variantAnimatedShapes анимирует кнопку переключения значков при нажатии и установке/снятии флажка.
TextButton TextButtonDefaults.animatedShapes анимирует текстовую кнопку при нажатии.
TextToggleButton TextToggleButtonDefaults.animatedShapes анимирует переключатель текста при нажатии, а TextToggleButtonDefaults.variantAnimatedShapes анимирует переключатель текста при нажатии и установке/снятии флажка.

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

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

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

Материал 2.5 Material 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() Удалено, так как не используется в Material 3 в Text или Icon.
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
androidx.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 и их аналогов в Material 2.5.

Material 3 Эквивалентный компонент Material 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 androidx.wear.compose.material.Scaffold (с 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 androidx.wear.compose.material.Scaffold (с 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.8.0-alpha01
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.

M2.5

import androidx.wear.compose.material.Chip

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

M3

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

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

В M3 появилась новая кнопка EdgeButton. EdgeButton доступен в четырех размерах: XS, S, M и L. EdgeButton реализации предоставляет значение по умолчанию для maxLines в зависимости от размера, которое можно изменить.

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

val state = rememberTransformingLazyColumnState()
ScreenScaffold(
    scrollState = state,
    edgeButton = {
        EdgeButton(
            onClick = { },
            modifier = Modifier.scrollable(
                state,
                orientation = Orientation.Vertical,
                reverseDirection = true,
                // Apply overscroll to the EdgeButton for proper scrolling behavior.
                overscrollEffect = rememberOverscrollEffect(),
            ),
        ) {
            Text(stringResource(R.string.show))
        }
    },
) { contentPadding ->
    TransformingLazyColumn(state = state, contentPadding = contentPadding) {
        // additional code here
        // ...
    }
}

Scaffold

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

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

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

M2.5

import androidx.wear.compose.material.Scaffold

Scaffold {...}

M3

    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 transformationSpec = rememberTransformationSpec()

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

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

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

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

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

    HorizontalPagerScaffold(pagerState = pagerState) {
        HorizontalPager(
            state = pagerState,
            flingBehavior =
                PagerScaffoldDefaults.snapWithSpringFlingBehavior(
                    state = pagerState
                ),
        ) { page ->
            AnimatedPage(pageIndex = page, pagerState = pagerState) {
                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 = "Pager sample")
                            }
                        }
                        item {
                            Card(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .transformedHeight(this, transformationSpec)
                                    .minimumVerticalContentPadding(
                                        CardDefaults.minimumVerticalListContentPadding
                                    ),
                                transformation = SurfaceTransformation(transformationSpec),
                            ) {
                                if (page == 0) {
                                    Text(text = "Page #$page. Swipe right")
                                } else {
                                    Text(text = "Page #$page. Swipe left and right")
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

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

@Composable
fun VerticalPagerScaffoldSample() {
    AppScaffold {
        val pagerState = rememberPagerState(pageCount = { 10 })

        VerticalPagerScaffold(pagerState = pagerState) {
            VerticalPager(
                state = pagerState,
                flingBehavior =
                    PagerScaffoldDefaults.snapWithSpringFlingBehavior(
                        state = pagerState
                    ),
            ) { page ->
                AnimatedPage(pageIndex = page, pagerState = pagerState) {
                    ScreenScaffold {
                        Column(
                            modifier = Modifier.fillMaxSize(),
                            horizontalAlignment = Alignment.CenterHorizontally,
                            verticalArrangement = Arrangement.Center,
                        ) {
                            Text(text = "Page #$page")
                            Spacer(modifier = Modifier.height(8.dp))
                            Text(text = "Swipe up and down")
                        }
                    }
                }
            }
        }
    }
}

Плейсхолдер

В API версий M2.5 и M3 есть некоторые различия. В M3 есть два модификатора плейсхолдера:

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

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

M2.5 M3
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 – часть androidx.wear.compose.foundation.lazy, которая добавляет поддержку масштабирования и морфинга анимаций в элементах списка во время прокрутки, улучшая пользовательский опыт. Мы настоятельно рекомендуем перенести приложения с ScalingLazyColumn на TransformingLazyColumn.

Как и в случае с ScalingLazyColumn, он позволяет rememberTransformingLazyColumnState() создать TransformingLazyColumnState, который будет запоминаться во всех композициях.

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

  • Modifier.transformedHeight, который позволяет рассчитать преобразованную высоту объектов с помощью TransformationSpec, можно использовать 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 и исходный код

Дизайн