开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
大家应该对theme已经很熟悉了,所谓Theme就是不同的style,例如颜色,item的形状,字体等方面。在Compose里面Theme也是针对这几个方面进行配置。看看MaterialTheme的定义:
fun MaterialTheme(
colors: Colors = MaterialTheme.colors,
typography: Typography = MaterialTheme.typography,
shapes: Shapes = MaterialTheme.shapes,
content: @Composable () -> Unit
)
在Compose里面,当你创建好工程的时候对于app独有的theme对象就有了。
fun ComposeExampleTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
在创建app的时候会产生类似这样的compoosable函数,color是我们在app的代码里面自定义的:
private val DarkColorPalette = darkColors(
primary = Purple200,
primaryVariant = Purple700,
secondary = Teal200
)
private val LightColorPalette = lightColors(
primary = Purple500,
primaryVariant = Purple700,
secondary = Teal200
/* Other default colors to override
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
*/
)
我们如果要改主题的颜色,那么相应的去换自定义的颜色就可以了。那需要怎么使用呢?
color = MaterialTheme.colors.primary
那现在会使用了,应该怎么切换theme呢?这个就要充分利用Composable函数了。如下示例代码:
var isDark by remember {
mutableStateOf(false)
}
ComposeExampleTheme(darkTheme = isDark) {
// A surface container using the 'background' color from the theme
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
Column() {
Box(modifier = Modifier
.fillMaxSize()
.wrapContentSize()
.weight(1f)
.border(BorderStroke(width = 2.dp, color = MaterialTheme.colors.primary))){
Text(text = "Hi,Compose!")
}
Button(onClick = { isDark = !isDark}) {
Text(text = "Change theme")
}
}
}
}
我们首先定义一个mutableState变量,然后在button onclick的时候改变这个值就可以切换相应的theme了。当state值变化的时候会触发composable函数的重组,从而达到切换theme的效果。需要说明的是这个一定要是一个state变量,这样才能触发composable函数。这个比之前切换theme简单多了。例子的效果如下:
那大家可能还有一些疑问,如果在MaterailTheme里面没有我想要的颜色怎么办呢?这个Compose也想到了,可以使用自定义的theme:
- 首先定义一个类来表述自定义的color:
class LocalColor(
var color1:Color = Color.Unspecified,
var color2:Color = Color.Unspecified,
var color3:Color = Color.Unspecified,
)
- 定义全局变量:
val localColorTheme = staticCompositionLocalOf { LocalColor() }
- 自定义不同theme下面的值,这里简单写了几个值:
val localDarkTheme = LocalColor(color1 = Color.White, color2 = Color.Red, color3 = Color.Gray)
val localLightTheme = LocalColor(color1 = Color.Black, color2 = Color.Green, color3 = Color.Blue)
- 使其生效,在定义theme的地方使用provider将其定义成类似一个全局变量,这样在其他使用到这个theme的地方都可以使用自定义的theme了。
val localColor = if(darkTheme) localDarkTheme else localLightTheme
CompositionLocalProvider(localColorTheme provides localColor){
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
上面举了自定义color的还可以自定义其他的资源。应用theme只要在根composable函数上面应用就可以了。