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

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

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

Тема

В обеих версиях 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
)

Гибкие шрифты

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

Стили текста

В 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
)

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

Преобразование фигур

В M3 добавлена функция Shape Morphing, которая позволяет фигурам менять форму в ответ на действия пользователя.

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

Кнопки Функция преобразования фигур
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.

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

Material 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() Удалено, так как не используется 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
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-alpha02
androidx.wear.compose.foundation.hierarchicalFocusGroup Используется для аннотирования composable-функций в приложении, чтобы отслеживать активную часть композиции и координировать фокус.
androidx.wear.compose.foundation.pager.HorizontalPager Горизонтально прокручиваемый пейджер, созданный на основе компонентов Compose Foundation с улучшениями, специфичными для Wear, для повышения производительности и соблюдения рекомендаций Wear OS.
androidx.wear.compose.foundation.pager.VerticalPager Вертикально прокручиваемый пейджер, созданный на основе компонентов Compose Foundation с улучшениями для Wear, повышающими производительность и соответствие рекомендациям 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

Scaffold в M3 отличается от M2.5. В M3 AppScaffold и новая composable-функция ScreenScaffold заменили Scaffold. 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 и исходный код

Дизайн