Jetpack Compose 提供 Material Design 這項產品,這是用於建立數位介面的全方位設計系統。Material Design 元件 (按鈕、資訊卡、切換按鈕等) 是以 Material Design 主題設定為基礎建構而成,能夠以系統化的方式自訂 Material Design,以更切合您產品品牌的方式呈現。Material Design 主題包含顏色、字體排版和形狀屬性。自訂這些屬性時,變更會自動反映在您建構應用程式的元件中。
Jetpack Compose 可透過 MaterialTheme 可組合項實作這些概念:
MaterialTheme( colors = // ... typography = // ... shapes = // ... ) { // app content }
設定要傳遞給 MaterialTheme 的參數,用來設定應用程式的主題。

顏色
顏色是在 Compose 中使用 Color 類別 (資料保留類別) 建立型式。
val Red = Color(0xffff0000) val Blue = Color(red = 0f, green = 0f, blue = 1f)
雖然您可以依照自己的偏好整理這些資料 (例如頂層常數、單例模式內部或定義內嵌),我們仍強烈建議您在主題中指定色彩,並從該處擷取色彩。這個方法可支援深色主題和巢狀主題。

Compose 提供 Colors 類別,以建立 Material Design 色彩系統的型式。Colors 提供建構工具函式來建立一組淺色或深色顏色:
private val Yellow200 = Color(0xffffeb46) private val Blue200 = Color(0xff91a4fc) // ... private val DarkColors = darkColors( primary = Yellow200, secondary = Blue200, // ... ) private val LightColors = lightColors( primary = Yellow500, primaryVariant = Yellow400, secondary = Blue700, // ... )
定義 Colors 後,您可以將其傳遞至 MaterialTheme:
MaterialTheme( colors = if (darkTheme) DarkColors else LightColors ) { // app content }
使用主題顏色
您可以使用 MaterialTheme.colors 擷取提供給 MaterialTheme 可組合項的 Colors。
Text( text = "Hello theming", color = MaterialTheme.colors.primary )
表面和內容顏色
許多元件都接受一組顏色和內容顏色:
Surface( color = MaterialTheme.colors.surface, contentColor = contentColorFor(color), // ... ) { /* ... */ } TopAppBar( backgroundColor = MaterialTheme.colors.primarySurface, contentColor = contentColorFor(backgroundColor), // ... ) { /* ... */ }
這不僅可讓您設定可組合項的色彩,還能為「內容」提供預設顏色 (包含在其中的可組合項)。許多可組合項預設會使用這個內容顏色。舉例來說,Text 會根據父項內容的顏色設定顏色,而 Icon 則會使用該顏色設定色調。

contentColorFor() 方法會擷取任何主題色彩的適當「開啟」顏色。舉例來說,如果您在 Surface 上設定 primary 背景顏色,就會使用此函式將 onPrimary 設為內容顏色。如果您設定了非主題的背景顏色,也應一併指定適當的內容顏色。請使用 LocalContentColor 從階層中的指定位置擷取目前背景偏好的內容顏色。
內容 Alpha 值
通常您會希望以不同的程度強調內容,做為告知重要性並提供視覺階層的方式。Material Design 文字易讀性建議建議採用不同程度的透明度,以傳達不同的重要性等級。
Jetpack Compose 會使用 LocalContentAlpha 實作這項功能。您可以為這個 CompositionLocal 提供值,從而為階層指定內容 Alpha。巢狀可組合項可使用這個值,將 Alpha 處理方式套用至內容。舉例來說,根據預設,Text 和 Icon 會使用 LocalContentColor 的組合調整值,以使用 LocalContentAlpha。Material Design 會指定某些標準 Alpha 值 (high、medium、disabled),這些值則由 ContentAlpha 物件建模。
// By default, both Icon & Text use the combination of LocalContentColor & // LocalContentAlpha. De-emphasize content by setting content alpha CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { Text( // ... ) } CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.disabled) { Icon( // ... ) Text( // ... ) }
如要進一步瞭解 CompositionLocal,請參閱使用 CompositionLocal 的本機範圍資料。
ContentAlpha.high。第二行包含較不重要的中繼資料,因此使用 ContentAlpha.medium。深色主題
在 Compose 中,為 MaterialTheme 可組合項提供不同的 Colors 組合,以實作淺色和深色主題:
@Composable fun MyTheme( darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { MaterialTheme( colors = if (darkTheme) DarkColors else LightColors, /*...*/ content = content ) }
在這個範例中,MaterialTheme 會包裝在其可組合函式中,該函式接受指定是否要使用深色主題的參數。在這種情況下,函式會查詢裝置主題設定,藉此取得 darkTheme 的預設值。
您可以使用像這樣的程式碼來檢查目前的 Colors 是淺色還是深色:
val isLightTheme = MaterialTheme.colors.isLight Icon( painterResource( id = if (isLightTheme) { R.drawable.ic_sun_24 } else { R.drawable.ic_moon_24 } ), contentDescription = "Theme" )
高度重疊
在 Material 中,深色主題中高度較高的途徑將取得高度重疊,以此方式調淡背景。途徑的高度越高 (提高使其更接近隱含光源),途徑顏色就會變得較淺。
使用深色時,Surface 可組合項會自動套用這些重疊,亦適用於使用途徑的其他材質可組合項:
Surface( elevation = 2.dp, color = MaterialTheme.colors.surface, // color will be adjusted for elevation /*...*/ ) { /*...*/ }
surface 顏色做為背景。由於資訊卡和底部導覽位於背景上方的不同高度層級,因此顏色會略有不同:資訊卡比背景顏色淡,底部導覽又比資訊卡更淡。如果是不涉及 Surface 的自訂情境,請使用 LocalElevationOverlay,也就是包含 ElevationOverlay (由 Surface 可組合項使用) 的 CompositionLocal:
// Elevation overlays // Implemented in Surface (and any components that use it) val color = MaterialTheme.colors.surface val elevation = 4.dp val overlaidColor = LocalElevationOverlay.current?.apply( color, elevation )
如要停用高度重疊,請在可組合函式階層中選擇要停用的位置提供 null:
MyTheme { CompositionLocalProvider(LocalElevationOverlay provides null) { // Content without elevation overlays } }
受限的輔色
在多數情況下,Material 會偏好使用 surface 顏色 (而非 primary 顏色),進而為深色主題推薦套用受限的輔色。根據預設,材質可組合項 (例如 TopAppBar 和 BottomNavigation) 會實作此行為。

針對自訂情境,請使用 primarySurface 擴充功能屬性:
Surface( // Switches between primary in light theme and surface in dark theme color = MaterialTheme.colors.primarySurface, /*...*/ ) { /*...*/ }
字體排版
Material 定義了字體系統,並建議您少用語意命名樣式。

Compose 會透過 Typography、TextStyle 和字型相關類別實作類型系統。Typography 建構函式提供每種樣式的預設值,因此您可以略過任何不想自訂的樣式:
val raleway = FontFamily( Font(R.font.raleway_regular), Font(R.font.raleway_medium, FontWeight.W500), Font(R.font.raleway_semibold, FontWeight.SemiBold) ) val myTypography = Typography( h1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W300, fontSize = 96.sp ), body1 = TextStyle( fontFamily = raleway, fontWeight = FontWeight.W600, fontSize = 16.sp ) /*...*/ ) MaterialTheme(typography = myTypography, /*...*/) { /*...*/ }
如要使用相同的字體,請指定 defaultFontFamily 參數,並省略任何 TextStyle 元素的 fontFamily:
val typography = Typography(defaultFontFamily = raleway) MaterialTheme(typography = typography, /*...*/) { /*...*/ }
使用文字樣式
TextStyle 元素是使用 MaterialTheme.typography 存取。依下列方式擷取 TextStyle 元素:
Text( text = "Subtitle2 styled", style = MaterialTheme.typography.subtitle2 )

形狀
Material 定義了形狀系統,可讓您定義大型、中型和小型元件的形狀。

Compose 透過 Shapes 類別實作形狀系統,讓您為每個尺寸類別指定 CornerBasedShape:
val shapes = Shapes( small = RoundedCornerShape(percent = 50), medium = RoundedCornerShape(0f), large = CutCornerShape( topStart = 16.dp, topEnd = 0.dp, bottomEnd = 0.dp, bottomStart = 16.dp ) ) MaterialTheme(shapes = shapes, /*...*/) { /*...*/ }
根據預設,許多元件都會使用這些形狀。舉例來說,Button、TextField 和 FloatingActionButton 預設為小型;AlertDialog 預設為中型;ModalDrawer 預設為大型。詳情請參閱形狀配置參考資料中的完整對應資訊。
使用形狀
Shape 元素是使用 MaterialTheme.shapes 存取。使用下列程式碼擷取 Shape 元素:
Surface( shape = MaterialTheme.shapes.medium, /*...*/ ) { /*...*/ }
預設樣式
在 Compose 中,沒有如同 Android 檢視畫面中預設樣式的概念。您可以自行建立包裝材質元件的 overload 可組合函式,藉此提供類似的功能。舉例來說,如要建立按鈕樣式,請將按鈕包裝在您自己的可組合函式中,這會直接設定您想要或需要變更的參數,然後以參數形式向包含的可組合項公開其他值。
@Composable fun MyButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary ), onClick = onClick, modifier = modifier, content = content ) }
主題重疊
您可以透過建立 MaterialTheme 可組合項的巢狀結構,在 Compose 中進行與 Android Views 主題重疊對等的設定。由於 MaterialTheme 會將顏色、字體排版和形狀預設為目前的主題值,如果主題只設定其中一項參數,其他參數仍會使用預設值。
此外,將以檢視模式為基礎的畫面遷移至 Compose 時,請留意 android:theme 屬性的使用情形。您可能需要在 Compose UI 樹狀結構的該部分中新增 MaterialTheme。
在這個範例中,大部分畫面的詳細資料畫面使用 PinkTheme,相關區段則使用 BlueTheme。以下螢幕截圖和程式碼說明瞭這個概念:
@Composable fun DetailsScreen(/* ... */) { PinkTheme { // other content RelatedSection() } } @Composable fun RelatedSection(/* ... */) { BlueTheme { // content } }
元件狀態
可互動 (已點擊、切換等) 的 Material 元件可以處於不同的視覺狀態。狀態包括已啟用、已停用、已按下等。
可組合項通常有 enabled 參數。設為 false 可禁止互動,並變更顏色和高度等屬性,以便透過視覺化方式傳達元件狀態。
enabled = true (左) 和 enabled = false (右) 的按鈕。在大部分情況下,您可以仰賴顏色和高度等預設值。如要設定不同狀態使用的值,可以使用各種類別和便利函式。請參考以下按鈕範例:
Button( onClick = { /* ... */ }, enabled = true, // Custom colors for different states colors = ButtonDefaults.buttonColors( backgroundColor = MaterialTheme.colors.secondary, disabledBackgroundColor = MaterialTheme.colors.onBackground .copy(alpha = 0.2f) .compositeOver(MaterialTheme.colors.background) // Also contentColor and disabledContentColor ), // Custom elevation for different states elevation = ButtonDefaults.elevation( defaultElevation = 8.dp, disabledElevation = 2.dp, // Also pressedElevation ) ) { /* ... */ }

enabled = true (左) 和 enabled = false (右) 的按鈕,使用調整後的顏色和高度值。漣漪效果
材質元件會透過分享關係圖來表示正在互動。如果您在階層中使用 MaterialTheme,則會使用 Ripple 做為預設的 Indication 內部修飾元 (例如 clickable 和 indication)。
在大部分情況下,您可以仰賴預設的 Ripple。如要設定外觀,可以使用 RippleTheme 變更顏色和 Alpha 等屬性。
您可以擴充 RippleTheme,並使用 defaultRippleColor 和 defaultRippleAlpha 公用程式函式。然後,您可以利用 LocalRippleTheme 在階層中提供自訂分享關係圖主題:
@Composable fun MyApp() { MaterialTheme { CompositionLocalProvider( LocalRippleTheme provides SecondaryRippleTheme ) { // App content } } } @Immutable private object SecondaryRippleTheme : RippleTheme { @Composable override fun defaultColor() = RippleTheme.defaultRippleColor( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) @Composable override fun rippleAlpha() = RippleTheme.defaultRippleAlpha( contentColor = MaterialTheme.colors.secondary, lightTheme = MaterialTheme.colors.isLight ) }

RippleTheme 產生不同漣漪值的按鈕。瞭解詳情
如要進一步瞭解 Compose 中的 Material Design 主題設定,請參閱下列其他資源。
程式碼研究室
影片
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- Compose 中的自訂設計系統
- 在 Compose 中從 Material 2 遷移至 Material 3
- Compose 中的無障礙功能