在 Compose for Wear OS 中從 Material 2.5 遷移至 Material 3

Material 3 Expressive 是新一代的 Material Design。提供更新後的主題設定、元件,以及動態色彩等個人化功能。

本指南主要說明如何將應用程式從 Wear Compose Material 2.5 (androidx.wear.compose) Jetpack 程式庫遷移至 Wear Compose Material 3 (androidx.wear.compose.material3) Jetpack 程式庫。

做法

如要將應用程式程式碼從 M2.5 遷移至 M3,請按照這篇指南所述的相同方法操作,特別是:

依附元件

M3 的套件和版本與 M2.5 不同:

M2.5

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

M3

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

請前往 Wear Compose 質感設計 3 版本頁面查看 M3 的最新版本。

Wear Compose Foundation 程式庫 1.6.0-alpha03 版導入了一些新元件,這些元件專為搭配 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.6.0-alpha03")
implementation("androidx.wear.compose:compose-navigation:1.6.0-alpha03")

主題

在 M2.5 和 M3 中,主題可組合項的名稱都是 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 = AppColorScheme,
        typography = AppTypography,
        shapes = AppShapes,
        motionScheme = AppMotionScheme,
        content = content
)

顏色

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

Color

已重新命名為「ColorScheme

13 種顏色

28 種顏色

全新的動態色彩主題設定

全新第三種顏色,可呈現更多樣的風格

動態色彩主題

M3 的其中一項新功能是動態色彩主題。如果使用者變更錶面顏色,UI 中的顏色也會隨之變更。

使用 dynamicColorScheme 函式實作動態色彩配置,並在動態色彩配置無法使用時,提供 defaultColorScheme 做為備用選項。

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

字體排版

M3 的字體排版系統與 M2 不同,且包含下列功能:

  • 九種全新文字樣式
  • 彈性字型,可自訂不同粗細、寬度和圓度的字體比例
  • 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 字型

設計人員可使用彈性字型,為特定大小指定字型寬度和粗細。

文字樣式

M3 提供下列 TextStyle。M3 各種元件預設會採用這些顏色。

字體排版

TextStyle

螢幕

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 類別:

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
)

以「在 Compose 中從 Material 2 遷移至 Material 3」一文中的「形狀」參數對應做為起點。

形狀漸變

M3 推出形狀變形功能:形狀現在會因應互動而變形。

形狀漸變行為適用於多種圓形按鈕,請參閱下列支援形狀漸變的按鈕清單:

按鈕

形狀漸變功能

IconButton

IconButtonDefaults.animatedShape() 會在按下時為圖示按鈕加上動畫效果

IconToggleButton

IconToggleButtonDefaults.animatedShape() 會在按下時為圖示切換按鈕加上動畫,並

IconToggleButtonDefaults.variantAnimatedShapes() 會在按下及勾選/取消勾選時,為圖示切換按鈕加上動畫效果

TextButton

TextButtonDefaults.animatedShape() 會在按下時為文字按鈕加上動畫效果

TextToggleButton

TextToggleButtonDefaults.animatedShapes() 會在按下時為文字切換按鈕加上動畫效果,而 TextToggleButtonDefaults.variantAnimatedShapes() 則會在按下時為文字切換按鈕加上動畫效果,並檢查/取消檢查

元件和版面配置

M3 支援 M2.5 的大多數元件和版面配置。不過,部分 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.IconButtonandroidx.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.CheckboxButtonandroidx.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 中的 TextIcon 未使用

androidx.wear.compose.material.PositionIndicator

androidx.wear.compose.material3.ScrollIndicator

androidx.wear.compose.material.RadioButton

沒有 M3 同等項目,請遷移至 androidx.wear.compose.material3.RadioButtonandroidx.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.AppScaffoldandroidx.wear.compose.material3.ScreenScaffold

androidx.wear.compose.material.SplitToggleChip

沒有對應的 M3 項目,請遷移至 androidx.wear.compose.material3.SplitCheckboxButton androidx.wear.compose.material3.SplitSwitchButtonandroidx.wear.compose.material3.SplitRadioButton

androidx.wear.compose.material.Switch

沒有 M3 同等項目,請遷移至 androidx.wear.compose.material3.SwitchButtonandroidx.wear.compose.material3.SplitSwitchButton

androidx.wear.compose.material.ToggleButton

androidx.wear.compose.material3.IconToggleButtonandroidx.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

已移除,因為 Wear OS 的 Material 3 Expressive 設計未納入這項元素

以下列出所有 Material 3 元件:

Material 3

Material 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 (搭配 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 (搭配 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.SwipeToRevealCardandroidx.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 程式庫中一些相關元件,這些元件首次在 1.6.0-alpha03 版中推出:

Wear Compose Foundation 1.6.0-alpha03

androidx.wear.compose.foundation.hierarchicalFocusGroup

用於在應用程式中為可組合項加註,追蹤組合的有效部分並協調焦點。

androidx.compose.foundation.pager.HorizontalPager

以 Compose Foundation 元件為基礎建構的水平捲動分頁檢視區塊,並針對 Wear 進行強化,以提升效能並符合 Wear OS 指南。

androidx.compose.foundation.pager.VerticalPager

垂直捲動分頁器,以 Compose Foundation 元件為基礎建構,並針對 Wear 進行強化,以提升效能並符合 Wear OS 指南。

androidx.wear.foundation.lazy.TransformingLazyColumn

可用於取代 ScalingLazyColumn,為每個項目新增捲動轉換效果。

按鈕

M3 的按鈕與 M2.5 不同。M2.5 晶片已由按鈕取代。Button 實作會為 TextmaxLinestextAlign 提供預設值。您可以在 Text 元素中覆寫這些預設值。

M2.5

import androidx.wear.compose.material.Chip

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

M3

import androidx.wear.compose.material3.Button

//M3 Buttons
Button(...)
CompactButton(...)
IconButton(...)
TextButton(...)

M3 也提供新的按鈕變化版本。詳情請參閱 Compose Material 3 API 參考資料總覽

M3 推出新按鈕:EdgeButtonEdgeButton 提供 4 種尺寸:XS、S、M 和 L。EdgeButton 實作方式會根據大小提供 maxLines 的預設值,且可自訂。

如果您使用 TransformingLazyColumnScalingLazyColumn,請將 EdgeButton 傳遞至 ScreenScaffold,以便變形,並隨著捲動改變形狀。請參閱下列程式碼,瞭解如何搭配使用 EdgeButtonScreenScaffoldTransformingLazyColumn

import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ScreenScaffold

ScreenScaffold(
   scrollState = state,
   contentPadding = contentPadding,
   edgeButton = {
      EdgeButton(...)
   }
){ contentPadding ->
   TransformingLazyColumn(state = state, contentPadding = contentPadding,){
   // additional code here
   }
}

Scaffold

M3 的 Scaffold 與 M2.5 不同。在 M3 中,AppScaffold 和新的 ScreenScaffold 可組合函式已取代 Scaffold。AppScaffoldScreenScaffold 會配置畫面結構,並協調 ScrollIndicatorTimeText 元件的轉場效果。

AppScaffold 可在應用程式內轉場期間 (例如滑動關閉),持續顯示靜態畫面元素 (例如 TimeText)。並為主要應用程式內容提供位置,通常由導覽元件 (例如 SwipeDismissableNavHost) 提供。

您要為每個 Activity 宣告一個 AppScaffold,並為每個畫面使用一個 ScreenScaffold

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 padding = rememberResponsiveColumnPadding(
        first = ColumnItemType.BodyText
    )

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

如果您使用 HorizontalPagerHorizontalPagerIndicator,可以遷移至 HorizontalPagerScaffoldHorizontalPagerScaffold放置在 AppScaffold 內。AppScaffoldHorizontalPagerScaffold 會配置 Pager 的結構,並協調 HorizontalPageIndicatorTimeText 元件的轉場效果。

HorizontalPagerScaffold 預設會在畫面中央邊緣顯示 HorizontalPageIndicator,並根據 Pager 是否正在分頁,協調顯示和隱藏 TimeTextHorizontalPageIndicator,這取決於 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 相同:

import androidx.wear.compose.material3.AppScaffold
import androidx.wear.compose.material3.HorizontalPagerScaffold
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.foundation.pager.VerticalPager
import androidx.wear.compose.foundation.pager.rememberPagerState

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 現在提供兩種修飾符:

如要瞭解 Placeholder 元件的其他變更,請參閱下表。

M2.5

M3

PlaceholderState.startPlaceholderAnimation

已移除

PlaceholderState.placeholderProgression

已移除

PlaceholderState.isShowContent

已重新命名為「!PlaceholderState.isVisible

PlaceholderState.isWipeOff

已移除

PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush

已移除

PlaceholderDefaults.placeholderBackgroundBrush

已移除

PlaceholderDefaults.placeholderChipColors

已移除

SwipeDismissableNavHost

SwipeDismissableNavHostwear.compose.navigation 的一部分。將這個元件與 M3 搭配使用時,M3 MaterialTheme 會更新 LocalSwipeToDismissBackgroundScrimColorLocalSwipeToDismissContentScrimColor

TransformingLazyColumn

TransformingLazyColumnwear.compose.lazy.foundation 的一部分,可支援在捲動期間縮放及變形清單項目的動畫,提升使用者體驗。

ScalingLazyColumn 類似,它提供 rememberTransformingLazyColumnState() 來建立 TransformingLazyColumnState,並在組合中保留該 TransformingLazyColumnState

如要新增縮放和變形動畫,請在每個清單項目中加入下列項目:

  • Modifier.transformedHeight,可讓您使用 TransformationSpec 計算項目的轉換高度,除非需要進一步自訂,否則可以使用 rememberTransformationSpec()
  • A 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,
                )
            }
        }
    }
}

如要進一步瞭解如何在 Compose 中從 M2.5 遷移至 M3,請參閱下列其他資源。

範例

API 參考資料和原始碼

設計