文章目錄
- Compose主題
- 需求一覽
- 默認的主題
- 自定義主題
- 實作需求
- Colors屬性不夠用?
Compose主題
Compose提供了系統化的方法來幫助我們自定義主題,這讓我們在實作暗黑主題以及其他顏色主題的時候非常非常的方便,
需求一覽
這節的需求很簡單,我們的App需要有藍,紅,綠,黃四種主題色,在點擊tab的時候分別切換不同的主題色,大致效果如下所示,

默認的主題
比如我們的工程名叫ComposeComing,那么工程建好后默認的Activity中會有如下代碼:
setContent {
ComposeComingTheme {
Surface(color = MaterialTheme.colors.background) {
}
}
}
上面有兩處代碼很可疑:
- ComposeComingTheme
- MaterialTheme.colors.background
首先這個 ComposeComingTheme() 函式我們點進去看下,你會發現該組合函式在 包名.ui.theme 檔案夾下的 Theme.kt 檔案中:
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
)
@Composable
fun ComposeComingTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
通過上述代碼,我們可以了解到:ComposeComingTheme 該組合函式在 MaterialTheme 上構建而成,MaterialTheme由colors、typography、shapes屬性組成,然后該組合函式默認根據系統 是否是暗黑主題 將 顏色屬性 進行了不同的定義,如果是暗黑主題使用DarkColorPalette,否則使用LightColorPalette,darkColors和lightColors都繼承自Colors,并有相關的默認顏色值,所以我們的需求-自定義不同的主題顏色可以在這里進行突破了,
Colors中的所有可配的值如下所示:
@Stable
class Colors(
primary: Color,
primaryVariant: Color,
secondary: Color,
secondaryVariant: Color,
background: Color,
surface: Color,
error: Color,
onPrimary: Color,
onSecondary: Color,
onBackground: Color,
onSurface: Color,
one rror: Color,
isLight: Boolean
)
而 MaterialTheme.colors.background 中最終呼叫的就是相關主題中設定的Colors的 background 屬性值,
自定義主題
接下來我們根據需求進行主題的自定義,首先給大家點顏色看看,在ui.theme檔案夾下的Color.kt檔案中添加如下顏色:
val blue = Color(0xFF579DFD)
val red = Color(0xFFEB685E)
val green = Color(0xFF27BA6A)
val yellow = Color(0xFFFFCB1F)
然后在ui.theme檔案夾下的Theme.kt檔案中自定義主題,在這里我們統一使用了lightColors,然后根據傳遞進來的主題的名稱將primary屬性設定為了不同的顏色,如下所示:
@Composable
fun MyAppTheme(
themeName: String = "blue",
content: @Composable() () -> Unit
) {
val colors = when (themeName) {
"red" -> lightColors(primary = red)
"green" -> lightColors(primary = green)
"yellow" -> lightColors(primary = yellow)
else -> lightColors(primary = blue)
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
這樣我們主題就已經定義好了,雖然只有primary屬性會根據不同主題變化,但是這足夠我們演示了,
接下來是TabRow的實作,我們將TabRow的背景顏色 backgroundColor 設定為剛定義的 primary 的顏色,點擊不同tab的時候設定不同的主題,并將點擊事件提升到上層處理,代碼如下所示,:
@Composable
fun MyTabRow(
onTabItemClick: (name: String) -> Unit,
indexDefault: Int = 0
) {
val indexState = remember {
mutableStateOf(indexDefault)
}
val colorsTab = arrayOf("blue", "red", "green", "yellow")
TabRow(
selectedTabIndex = indexState.value,
modifier = Modifier
.fillMaxWidth()
.height(46.dp),
backgroundColor = MaterialTheme.colors.primary
) {
for ((index, name) in colorsTab.withIndex()) {
Tab(
selected = index == indexState.value,
onClick = {
indexState.value = index
onTabItemClick(colorsTab[index])
},
modifier = Modifier.fillMaxHeight(),
) {
Text(
text = name,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
textAlign = TextAlign.Center
)
}
}
}
}
先來預覽下吧,我們在自定的主題MyAppTheme中組合MyTabRow,然后給定相關的主題顏色,這里默認預覽紅色和綠色的主題:
@Preview(showBackground = true)
@Composable
fun RedThemePreview() {
MyAppTheme(themeName = "red") {
MyTabRow(
onTabItemClick = {},
indexDefault = 1
)
}
}
@Preview(showBackground = true)
@Composable
fun GreenThemePreview() {
MyAppTheme(themeName = "green") {
MyTabRow(
onTabItemClick = {},
indexDefault = 2
)
}
}
預覽效果如下所示:

實作需求
預覽圖沒有問題,接下來就是整體的實作了,反正就一點 – 資料驅動,視圖自回應,在onCreate()函式中:
setContent {
val themeName = remember {
mutableStateOf("blue")
}
MyAppTheme(themeName = themeName.value) {
Column {
MyTabRow(onTabItemClick = {
themeName.value = it
})
}
}
}
這樣,我們點擊不同tab的時候,改變themeName的值,MyAppTheme會自動根據相應的值進行主題的切換,是不是就達到了如下效果呢:

Colors屬性不夠用?
上述需求實在是太簡單了,但是實際開發中我們可能有很多種地方都定義了不同的顏色,而Colors中只提供了12個相關顏色的定義,不夠用啊!!!
那怎么辦呢?擴展,字面意義上的擴展,同時也是kotlin中的擴展,直接給Colors擴展相關的屬性:
val Colors.myTabRowBackground: Color
@Composable get() = if (isLight) red else blue
但是這種方式明顯有弊端,就是只能根據是否是暗黑主題進行顏色的配置,無法支持到我們上述的那么多種主題,而且也比較麻煩,
而且我查遍了全網也沒有見到使用var來進行屬性擴展的示例,難道是不支持么?扔物線的視頻讓我自己研究,其他培訓機構的老師講到這里直接卡殼了,我需要給這個擴展的屬性進行賦值和取值的操作,求指點,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/286350.html
標籤:其他
