Compose官方推荐使用Surface来给任何可组合项设置颜色,Surface的color属性就默认设置了 MaterialTheme.colors.surface色值。
scss
Row(Modifier.background(MaterialTheme.colors.primary)) // 不推荐
Surface(color = MaterialTheme.colors.primary) { // 推荐
Row(
...
)
}
Surface(
color: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(color),
...
)
TopAppBar(
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
...
)
实现暗色主题,可以使用Preview的uiMode=UI_MODE_NIGHT_YES,还可以使用TestTheme(darkTheme = true),前提是内容要使用Surface。
kotlin
@Composable
private fun Greetings() {
Surface {
Text(text = "July 2021")
Icon(imageVector = Icons.Filled.AccountBox, contentDescription = null)
}
}
@Preview(
widthDp = 320,
uiMode = UI_MODE_NIGHT_YES,
name = "Dark"
)
@Preview(widthDp = 320)
@Composable
fun GreetingsPreview() {
TestTheme {
Greetings()
}
}
@Preview(widthDp = 320)
@Composable
fun GreetingsPreviewAnother() {
TestTheme(darkTheme = false) {
Greetings()
}
}
Surface的细节如下:
kotlin
fun Surface(
modifier: Modifier = Modifier,
shape: Shape = RectangleShape,
color: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = contentColorFor(color),
...
)
fun contentColorFor(backgroundColor: Color) =
MaterialTheme.colorScheme.contentColorFor(backgroundColor).takeOrElse {
LocalContentColor.current
}
// color若为primary的颜色值,则contentColor为 onPrimary的颜色值,二者一一对应
fun ColorScheme.contentColorFor(backgroundColor: Color): Color =
when (backgroundColor) {
primary -> onPrimary
secondary -> onSecondary
tertiary -> onTertiary
background -> onBackground
error -> onError
surface -> onSurface
surfaceVariant -> onSurfaceVariant
primaryContainer -> onPrimaryContainer
secondaryContainer -> onSecondaryContainer
tertiaryContainer -> onTertiaryContainer
errorContainer -> onErrorContainer
inverseSurface -> inverseOnSurface
else -> Color.Unspecified
}
Surface 的color 默认值是MaterialTheme.colorScheme.surface,contentColor的color 默认值是MaterialTheme.colorScheme.onSurface
项目的theme文件中LightColorScheme/DarkColorScheme会给MaterialTheme的colorScheme重新赋值,若LightColorScheme/DarkColorScheme未定义surface和onSurface,则使用系统默认的颜色。
以darkColorScheme为例
ini
fun darkColorScheme(
primary: Color = ColorDarkTokens.Primary,
onPrimary: Color = ColorDarkTokens.OnPrimary,
...
secondary: Color = ColorDarkTokens.Secondary,
onSecondary: Color = ColorDarkTokens.OnSecondary,
...
background: Color = ColorDarkTokens.Background,
onBackground: Color = ColorDarkTokens.OnBackground,
surface: Color = ColorDarkTokens.Surface,
onSurface: Color = ColorDarkTokens.OnSurface,
...
): ColorScheme =
ColorScheme(
primary = primary,
onPrimary = onPrimary,
...
secondary = secondary,
onSecondary = onSecondary,
...
background = background,
onBackground = onBackground,
surface = surface, //Color(red = 28, green = 27, blue = 31)
onSurface = onSurface, // Color(red = 230, green = 225, blue = 229)
...
)
故TestTheme(darkTheme = true)或uiMode = UI_MODE_NIGHT_YES时,color即整个平面为黑色,contentColor即text/icon为白色。反之同理。
若theme中定义
ini
private val DarkColorScheme = darkColorScheme(
surface = Color.Green,
onSurface = Color.Red,
}
private val LightColorScheme = lightColorScheme(
surface = Color.Yellow,
onSurface = Color.Gray,
}
则效果为:
若theme中定义
ini
private val DarkColorScheme = darkColorScheme(
primary = Color.Red,
onPrimary = Color.Green
)
private val LightColorScheme = lightColorScheme(
primary = Color.Gray,
onPrimary = Color.Yellow
)
修改Surface的color为MaterialTheme.colorScheme.primary ,则contentColor默认找MaterialTheme.colorScheme.onPrimary 如:
ini
Surface(color = MaterialTheme.colorScheme.primary)
效果如下
参考:
使用 Material 3 在 Compose 中设置主题 | Android Developers (google.cn)
初识 MaterialTheme | 你好 Compose (jetpackcompose.cn)
Surface | 你好 Compose (jetpackcompose.cn)
Jetpack-Compose 学习笔记(六)------ Compose 主题 Theme 一探究竟,换肤还能如此 Easy?-腾讯云开发者社区-腾讯云 (tencent.com)