Compose 中的質感設計 3

Jetpack Compose 可讓您實作 Material Design 3,這是新一代的 Material Design。Material 3 提供更新後的主題設定和元件,以及動態色彩等 Material You 個人化功能,可呼應 Android 12 以上版本的全新視覺風格和系統 UI。

以下我們將以 Reply 範例應用程式為例,示範如何實作 Material Design 3。Reply 範例完全採用 Material Design 3。

使用 Material Design 3 的 Reply 範例應用程式
圖 1:使用 Material Design 3 的 Reply 範例應用程式

依附元件

如要在 Compose 應用程式中開始使用 Material 3,請將 Compose Material 3 依附元件新增至 build.gradle 檔案:

implementation "androidx.compose.material3:material3:$material3_version"

加入依附元件後,您就可以開始在應用程式中加入 Material Design 系統,包括顏色、字體排版和形狀。

實驗性 API

部分 M3 API 屬於實驗性質。在此情況下,您必須使用 ExperimentalMaterial3Api 註解,在函式或檔案層級選擇加入:

// import androidx.compose.material3.ExperimentalMaterial3Api
@Composable
fun AppComposable() {
    // M3 composables
}

Material Design 主題設定

M3 主題包含下列子系統:色彩配置字體排版形狀。自訂這些值時,系統會自動在您用於建構應用程式的 M3 元件中反映變更。

Material Design 的子系統:顏色、字體排版和形狀
圖 2:Material Design 的子系統:顏色、字體排版和形狀

Jetpack Compose 可透過 M3 MaterialTheme 可組合項實作這些概念:

MaterialTheme(
    colorScheme = /* ...
    typography = /* ...
    shapes = /* ...
) {
    // M3 app content
}

如要為應用程式內容設定主題,請定義應用程式專屬的色彩配置、字體排版和形狀。

色彩配置

色彩配置的基礎是五組主要顏色,每個顏色都與 Material 3 元件使用的 13 種色調調色盤相關。舉例來說,以下是 Reply 淺色主題的色彩配置:

Reply 範例應用程式的淺色色彩配置
圖 3。Reply 範例應用程式的淺色色彩配置

如要進一步瞭解色彩配置和顏色角色,請前往這個網頁

產生色彩配置

雖然您可以手動建立自訂 ColorScheme,但使用品牌的來源色彩來產生這個類別是較容易的方式。您可以使用 Material Design 主題建構工具執行這項操作,並視需要匯出 Compose 主題設定程式碼。系統會產生下列檔案:

  • Color.kt 包含主題的顏色,以及針對淺色和深色主題顏色定義的所有角色。

val md_theme_light_primary = Color(0xFF476810)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFC7F089)
// ..
// ..

val md_theme_dark_primary = Color(0xFFACD370)
val md_theme_dark_onPrimary = Color(0xFF213600)
val md_theme_dark_primaryContainer = Color(0xFF324F00)
// ..
// ..

  • Theme.kt 包含淺色和深色色彩配置,以及應用程式主題的設定。

private val LightColorScheme = lightColorScheme(
    primary = md_theme_light_primary,
    onPrimary = md_theme_light_onPrimary,
    primaryContainer = md_theme_light_primaryContainer,
    // ..
)
private val DarkColorScheme = darkColorScheme(
    primary = md_theme_dark_primary,
    onPrimary = md_theme_dark_onPrimary,
    primaryContainer = md_theme_dark_primaryContainer,
    // ..
)

@Composable
fun ReplyTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme =
        if (!darkTheme) {
            LightColorScheme
        } else {
            DarkColorScheme
        }
    MaterialTheme(
        colorScheme = colorScheme,
        content = content
    )
}

如要支援淺色和深色主題,請使用 isSystemInDarkTheme()。根據系統設定,定義要使用的色彩配置:淺色或深色。

動態色彩配置

動態色彩是 Material You 的關鍵部分,其中演算法會從使用者的桌布衍生自訂色彩,並套用至其應用程式和系統 UI。這個調色盤是用來做為產生淺色和深色配置的起點。

從桌布 (左圖) 和預設應用程式主題 (右圖) 套用 Reply 範例應用程式的動態主題設定
圖 4. 從桌布 (左側) 和預設應用程式主題 (右側) 套用 Reply 範例應用程式的動態主題設定

動態色彩適用於 Android 12 以上版本。如有動態顏色可用,您可以設定動態 ColorScheme。如果沒有,您應改回使用自訂的淺色或深色 ColorScheme

ColorScheme 提供建構工具函式,用於建立動態淺色深色色彩配置:

// Dynamic color is available on Android 12+
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colors = when {
    dynamicColor && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
    dynamicColor && !darkTheme -> dynamicLightColorScheme(LocalContext.current)
    darkTheme -> DarkColorScheme
    else -> LightColorScheme
}

顏色使用情形

您可以透過 MaterialTheme.colorScheme 存取應用程式中的 Material 主題顏色:

Text(
    text = "Hello theming",
    color = MaterialTheme.colorScheme.primary
)

每個顏色角色都可以用在各種位置,視元件的狀態、顯眼程度和強調效果而定。

  • 「Primary」是基本顏色,用於主要元件,例如顯眼的按鈕、啟用中狀態,以及升高表面的色調。
  • 次要主要顏色用於 UI 中較不顯眼的元件,例如篩選器方塊,並擴大色彩表達的機會。
  • 三次要主要顏色可用於產生對比強調色,用於平衡主要和次要顏色,或引起對某個元素的高度關注。

「Reply」範例應用程式設計會在 primary-container 上方使用 on-primary-container 顏色,以強調所選項目。

使用 on-primary-container 顏色的主容器和文字欄位。
圖 5:使用 on-primary-container 顏色的主容器和文字欄位。

Card(
    colors = CardDefaults.cardColors(
        containerColor =
        if (isSelected) MaterialTheme.colorScheme.primaryContainer
        else
            MaterialTheme.colorScheme.surfaceVariant
    )
) {
    Text(
        text = "Dinner club",
        style = MaterialTheme.typography.bodyLarge,
        color =
        if (isSelected) MaterialTheme.colorScheme.onPrimaryContainer
        else MaterialTheme.colorScheme.onSurface,
    )
}

您可以在這裡看到「回覆」導覽匣中,次要和三次要容器顏色如何用於對比,以便強調和突顯內容。

浮動式動作按鈕的三級容器和在三級容器上的組合。
圖 6。適用於懸浮動作按鈕的三級容器和在三級容器上的組合。

字體排版

Material Design 3 定義了類型調整,包括從 Material Design 2 改編的文字樣式。此外,命名和分組功能也經過簡化,包括顯示、廣告標題、標題、內文和標籤 (皆有大、中和小三種尺寸)。

Material Design 3 的預設排版比例
圖 7. Material Design 3 的預設字體排版比例
M3 預設字型大小/行高
displayLarge Roboto 57/64
displayMedium Roboto 45/52
displaySmall Roboto 36/44
headlineLarge Roboto 32/40
headlineMedium Roboto 28/36
headlineSmall Roboto 24/32
titleLarge New- Roboto Medium 22/28
titleMedium Roboto Medium 16/24
titleSmall Roboto Medium 14/20
bodyLarge Roboto 16/24
bodyMedium Roboto 14/20
bodySmall Roboto 12/16
labelLarge Roboto Medium 14/20
labelMedium Roboto Medium 12/16
labelSmall New Roboto Medium, 11/16

定義字體排版

Compose 提供 M3 Typography 類別,配合現有的 TextStyle字型相關 類別,可建立 Material 3 類型調整型式。Typography 建構函式提供每種樣式的預設值,因此您可以略過任何不想自訂的參數:

val replyTypography = Typography(
    titleLarge = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 22.sp,
        lineHeight = 28.sp,
        letterSpacing = 0.sp
    ),
    titleMedium = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.15.sp
    ),
    // ..
)
// ..

內文大、內文中和標籤中,用於不同字體排版用法。
圖 8:內文大、內文中和標籤中,用於不同字體排版用法。

您的產品很可能不需要使用 Material Design 輸入比例的全部 15 個預設樣式。在這個範例中,系統會選擇五種大小,並省略其餘大小。

您可以變更 TextStyle字型相關屬性的預設值,自訂字體排版,例如 fontFamilyletterSpacing

bodyLarge = TextStyle(
    fontWeight = FontWeight.Normal,
    fontFamily = FontFamily.SansSerif,
    fontStyle = FontStyle.Italic,
    fontSize = 16.sp,
    lineHeight = 24.sp,
    letterSpacing = 0.15.sp,
    baselineShift = BaselineShift.Subscript
),

定義 Typography 後,請將其傳遞至 M3 MaterialTheme

MaterialTheme(
    typography = replyTypography,
) {
    // M3 app Content
}

使用文字樣式

您可以使用 MaterialTheme.typography 擷取提供給 M3 MaterialTheme 可組合項的字體排版:

Text(
    text = "Hello M3 theming",
    style = MaterialTheme.typography.titleLarge
)
Text(
    text = "you are learning typography",
    style = MaterialTheme.typography.bodyMedium
)

如要進一步瞭解 Material 指南,請參閱「套用字體排版」一文。

形狀

Material 表面可用不同形狀顯示。形狀可用於吸引注意、識別元件、傳達狀態,以及呈現品牌風格。

形狀比例定義容器角落的樣式,提供從方形到完全圓形的各種圓角。

定義形狀

Compose 提供含有擴展參數的 M3 Shapes 類別,可支援新的 M3 形狀。M3 形狀比例與輸入比例類似,可讓您在 UI 中呈現多種形狀。

形狀大小分為以下幾種:

  • 特小
  • 特大

根據預設,每個形狀都有預設值,但您可以覆寫這些值:

val replyShapes = Shapes(
    extraSmall = RoundedCornerShape(4.dp),
    small = RoundedCornerShape(8.dp),
    medium = RoundedCornerShape(12.dp),
    large = RoundedCornerShape(16.dp),
    extraLarge = RoundedCornerShape(24.dp)
)

定義 Shapes 後,即可將其傳遞至 M3 MaterialTheme

MaterialTheme(
    shapes = replyShapes,
) {
    // M3 app Content
}

使用形狀

您可以為 MaterialTheme 中的所有元件自訂形狀比例,也可以針對個別元件自訂。

套用中型和大型形狀的預設值:

Card(shape = MaterialTheme.shapes.medium) { /* card content */ }
FloatingActionButton(
    shape = MaterialTheme.shapes.large,
    onClick = {
    }
) {
    /* fab content */
}

在「回覆」範例應用程式中,卡片使用中型形狀,懸浮動作按鈕則使用大型形狀。
圖 9。在「回覆」範例應用程式中,資訊卡使用中型形狀,懸浮動作按鈕使用大型形狀

在 Compose 中,您還可以使用另外兩種形狀:RectangleShapeCircleShape。矩形沒有框線半徑,圓形則會顯示完整的圓形邊緣:

Card(shape = RectangleShape) { /* card content */ }
Card(shape = CircleShape) { /* card content */ }

以下範例展示了部分已套用預設形狀值的元件:

所有 Material 3 元件的預設形狀值。
圖 10. 所有 Material 3 元件的預設形狀值。

如要進一步瞭解 Material 指南,請參閱「套用形狀」一文。

強調效果

M3 中的強調效果會使用各種顏色變化及其色彩組合。在 M3 中,有兩種方法可為 UI 新增強調效果:

  • 使用表面、surface-variant 和背景,搭配已擴充 M3 色彩系統的 on-surface 和 on-surface-variants 顏色。舉例來說,表面可與 on-surface-variant 搭配使用,surface-variant 可與 on-surface 搭配使用,藉此提供不同程度的強調效果。
使用中性色彩組合強調重點。
圖 11. 使用中性色彩組合強調重點。
  • 為文字使用不同的字型粗細。如上所述,您可以為輸入比例提供自訂粗細,以達到不同的強調效果。

bodyLarge = TextStyle(
    fontWeight = FontWeight.Bold
),
bodyMedium = TextStyle(
    fontWeight = FontWeight.Normal
)

高度

Material 3 主要使用色調色彩重疊來表示高度。這是區分容器和途徑的新方式,提高色調高度除了陰影之外,需使用較為顯著的色調。

搭配陰影高度的色調高度
圖 12。搭配陰影高度的色調高度 E

深色主題中的高度重疊在 Material 3 中也已改為色調色彩重疊。重疊顏色來自主要色彩運算單元。

Material Design 3 中的陰影高度與色調高度
圖 13。Material Design 3 中的陰影高度與色調高度比較

M3 Surface 是大多數 M3 元件的備用可組合函式,同時支援色調及陰影高度:

Surface(
    modifier = Modifier,
    tonalElevation = /*...
    shadowElevation = /*...
) {
    Column(content = content)
}

Material 元件

Material Design 提供豐富的 Material 元件 (例如按鈕、方塊、資訊卡、導覽列),這些元件已遵循 Material 主題設定,可協助您打造美觀的 Material Design 應用程式。您可以開始使用內建預設屬性的元件。

Button(onClick = { /*..*/ }) {
    Text(text = "My Button")
}

M3 提供相同元件的多個版本,可根據重點和注意力在不同角色中使用。

從 FAB、Primary 到 Text 按鈕的按鈕強調
圖 14。按鈕強調效果從 FAB、Primary 到 Text 按鈕
  • 用於最高強調動作的展開式懸浮動作按鈕:

ExtendedFloatingActionButton(
    onClick = { /*..*/ },
    modifier = Modifier
) {
    Icon(
        imageVector = Icons.Default.Edit,
        contentDescription = stringResource(id = R.string.edit),
    )
    Text(
        text = stringResource(id = R.string.add_entry),
    )
}

  • 用於強調動作的填滿型按鈕:

Button(onClick = { /*..*/ }) {
    Text(text = stringResource(id = R.string.view_entry))
}

  • 低強調動作的文字按鈕:

TextButton(onClick = { /*..*/ }) {
    Text(text = stringResource(id = R.string.replated_articles))
}

您可以進一步瞭解 Material 按鈕和其他元件。Material 3 提供多種元件套件,例如按鈕、應用程式列、導覽元件,這些元件專為不同用途和螢幕大小而設計。

Material 也提供多個導覽元件,可根據不同的螢幕大小和狀態協助您實作導覽功能。

NavigationBar 適用於密集裝置,可讓您指定 5 個或更少的目標:

NavigationBar(modifier = Modifier.fillMaxWidth()) {
    Destinations.entries.forEach { replyDestination ->
        NavigationBarItem(
            selected = selectedDestination == replyDestination,
            onClick = { },
            icon = { }
        )
    }
}

NavigationRail 適用於小型至中型平板電腦或橫向模式的手機。這項功能可為使用者提供符合人體工學的體驗,並改善這些裝置的使用者體驗。

NavigationRail(
    modifier = Modifier.fillMaxHeight(),
) {
    Destinations.entries.forEach { replyDestination ->
        NavigationRailItem(
            selected = selectedDestination == replyDestination,
            onClick = { },
            icon = { }
        )
    }
}

展示底部導覽列(左) 和 NavigationRail(右) 的 Reply
圖 15。回覆展示:BottomNavigationBar (左) 和 NavigationRail (右)

在預設主題設定中使用這兩種回覆,為所有裝置尺寸提供沉浸式使用者體驗。

NavigationDrawer 適用於中型至大型平板電腦,因為這類裝置有足夠的空間顯示詳細資料。您可以同時使用 PermanentNavigationDrawerModalNavigationDrawerNavigationRail

PermanentNavigationDrawer(modifier = Modifier.fillMaxHeight(), drawerContent = {
    Destinations.entries.forEach { replyDestination ->
        NavigationRailItem(
            selected = selectedDestination == replyDestination,
            onClick = { },
            icon = { },
            label = { }
        )
    }
}) {
}

回覆:展示固定式導覽匣
圖 16。Reply 展示固定式導覽匣

導覽選項可改善使用者體驗、符合人體工學及提高可及性。如要進一步瞭解 Material Design 導覽元件,請參閱 Compose 自動調整式程式碼研究室

自訂元件的主題設定

M3 鼓勵個人化和彈性。所有元件都會套用預設顏色,但會提供彈性的 API,以便在需要時自訂顏色。

大多數元件 (例如卡片和按鈕) 都會提供預設物件,可公開顏色和高度介面,方便您修改元件以自訂:

val customCardColors = CardDefaults.cardColors(
    contentColor = MaterialTheme.colorScheme.primary,
    containerColor = MaterialTheme.colorScheme.primaryContainer,
    disabledContentColor = MaterialTheme.colorScheme.surface,
    disabledContainerColor = MaterialTheme.colorScheme.onSurface,
)
val customCardElevation = CardDefaults.cardElevation(
    defaultElevation = 8.dp,
    pressedElevation = 2.dp,
    focusedElevation = 4.dp
)
Card(
    colors = customCardColors,
    elevation = customCardElevation
) {
    // m3 card content
}

如要進一步瞭解如何自訂 Material 3,請參閱這篇文章

系統 UI

Material You 的某些面向,來自 Android 12 以上版本的全新視覺樣式和系統 UI。兩個主要部分是分享關係圖和過度捲動的變更。您無須採取額外工作就能導入這些變更。

漣漪

按下時,分享關係圖現在使用細微的火花來照亮途徑。 Compose Material 分享關係圖在 Android 手機上使用平台 RippleDrawable,因此 Android 12 以上版本所有材質元件均可使用火花分享關係圖。

M2 和 M3 的漣漪效果
圖 17。M2 與 M3 的漣漪效果

過度捲動

過度捲動現在可以在捲動容器的邊緣使用延展效果。無論 API 級別為何,在 Compose Foundation 1.1.0 以上版本中,捲動容器可組合項 (例如 LazyColumnLazyRowLazyVerticalGrid) 的延伸過度捲動設定預設為開啟。

在容器邊緣使用延展效果的過度捲動
圖 18。在容器邊緣使用延展效果的過度捲動

無障礙設定

Material 元件內建的無障礙標準,旨在提供包容性產品設計的基礎。瞭解產品的無障礙性,有助於提升所有使用者的使用體驗,包括視力不佳、失明、聽力障礙、認知障礙、動作障礙或情境障礙 (例如手臂骨折) 的使用者。

顏色無障礙設計

動態色彩可滿足無障礙標準的色彩對比度。色調調色盤系統對於讓任何色彩配置皆可在預設情況下使用無障礙功能至關重要。

Material 的色彩系統提供標準的色調值和測量方法,可用於達到一目瞭然的對比度。

Reply 範例應用程式:原色、二次色和三次色調色盤 (由上至下)
圖 19。Reply 範例應用程式:原色、二次色和三次色調色盤 (由上至下)

所有 Material 元件和動態主題設定都已使用上述顏色角色,這些角色來自一組色調調色盤,是為了滿足無障礙需求而選取。不過,如果您要自訂元件,請務必使用適當的顏色角色,避免不相符。

在原色上使用 on-primary,在 primary-container 上使用 on-primary-container,並對其他強調色和中性色採取相同做法,為使用者提供清楚易懂的顏色對比。

在原色上使用第三層容器,會為使用者提供對比度不佳的按鈕:

// ✅ Button with sufficient contrast ratio
Button(
    onClick = { },
    colors = ButtonDefaults.buttonColors(
        containerColor = MaterialTheme.colorScheme.primary,
        contentColor = MaterialTheme.colorScheme.onPrimary
    )
) {
}

// ❌ Button with poor contrast ratio
Button(
    onClick = { },
    colors = ButtonDefaults.buttonColors(
        containerColor = MaterialTheme.colorScheme.tertiaryContainer,
        contentColor = MaterialTheme.colorScheme.primaryContainer
    )
) {
}

對比度充足 (左) 與對比度不佳 (右)
圖 20。對比度充足 (左) 與對比度不足 (右) 的比較

字體排版無障礙

M3 類型比例會更新靜態類型漸層和值,提供簡化但動態的大小類別架構,可在不同裝置間調整大小。

舉例來說,在 M3 中,可根據裝置情境 (例如手機或平板電腦) 為「Display Small」指派不同的值。

大螢幕

Material 提供自適應版面配置和折疊式裝置的指南,讓使用者能輕鬆存取應用程式,並改善人體工學,讓使用者能輕鬆握住大型裝置。

Material 提供各種導覽,協助您為大型裝置提供更優質的使用者體驗。

如要進一步瞭解 Android 大螢幕應用程式品質指南,並查看自動調整式和無障礙設計的 回覆範例,請參閱相關說明。

瞭解詳情

如要進一步瞭解 Compose 中的材質主題設定,請參閱下列資源:

範例應用程式

文件

API 參考資料和原始碼

影片