Compose中的主题
# 设置Material主题
Material主题主要包含三个属性: 颜色、排版和形状,API如下:
@Composable
fun MaterialTheme(
colors: Colors = MaterialTheme.colors, // 颜色集合
typography: Typography = MaterialTheme.typography, // 排版集合
shapes: Shapes = MaterialTheme.shapes, // 形状集合
content: @Composable () -> Unit // 要展示的内容
)
2
3
4
5
6
7
# 颜色
class Colors(
primary: Color, // 主颜色,屏幕和元素都用这个颜色
primaryVariant: Color, // 用于区分主颜色,比如app bar和system bar
secondary: Color, // 强调色,悬浮按钮,单选/复选按钮,高亮选中的文本,链接和标题
secondaryVariant: Color, // 用于区分强调色
background: Color, // 背景色,在可滚动项下面展示
surface: Color, // 表层色,展示在组件表层,比如卡片,清单和菜单(CardView,SheetLayout,Menu)等
error: Color, // 错误色,展示错误信息,比如TextField的提示信息
onPrimary: Color, // 在主颜色primary之上的文本和图标的颜色
onSecondary: Color, // 在强调色secondary之上的文本和图标的颜色
onBackground: Color, // 在背景色background之上的文本和图标的颜色
onSurface: Color, // 在表层色surface之上的文本和图标的颜色
onError: Color, // 在错误色error之上的文本和图标的颜色
isLight: Boolean // 是否是浅色模式
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 排版
class Typography internal constructor(
val h1: TextStyle, // 一级标题
val h2: TextStyle,
val h3: TextStyle,
val h4: TextStyle,
val h5: TextStyle,
val h6: TextStyle,
val subtitle1: TextStyle, // 一级副标题
val subtitle2: TextStyle,
val body1: TextStyle, // 一级内容
val body2: TextStyle,
val button: TextStyle, // 按钮使用
val caption: TextStyle, // 说明文字
val overline: TextStyle // 页眉/页脚
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这里主要定义了各级标题/副标题,以及内容区的字体属性,至于TextStyle的具体属性可以看这里: Compose中的Text (opens new window)
# 形状
class Shapes(
// 小组件使用的形状,比如: Button,SnackBar,悬浮按钮等
val small: CornerBasedShape = RoundedCornerShape(4.dp),
// 中组件使用的形状,比如Card(就是CardView),AlertDialog等
val medium: CornerBasedShape = RoundedCornerShape(4.dp),
// 大组件使用的形状,比如ModalDrawer或者ModalBottomSheetLayout(就是抽屉布局和清单布局)
val large: CornerBasedShape = RoundedCornerShape(0.dp)
)
2
3
4
5
6
7
8
9
10
11
# 使用
现在让我们来try try,首先我们来定义颜色,代码如下:
// 定义深色模式下使用的颜色
private val DarkColorPalette = darkColors(
primary = Color.White,
onPrimary = Color.Red,
secondary = Color.Black,
surface = Color.Green,
)
// 定义浅色模式下使用的颜色
private val LightColorPalette = lightColors(
primary = Color.Black,
onPrimary = Color.Yellow,
secondary = Color.White,
surface = Color.Blue
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
代码很简单,只定义了深色和浅色模式下的几种颜色,其实Compose已经内置有颜色可供使用了,比如代码中的darkColors
和lightColors
,可以自行翻阅源码查看,里面只是提供了颜色参考。比如darkColors
:
fun darkColors(
primary: Color = Color(0xFFBB86FC),
primaryVariant: Color = Color(0xFF3700B3),
secondary: Color = Color(0xFF03DAC6),
secondaryVariant: Color = secondary,
background: Color = Color(0xFF121212),
surface: Color = Color(0xFF121212),
error: Color = Color(0xFFCF6679),
onPrimary: Color = Color.Black,
onSecondary: Color = Color.Black,
onBackground: Color = Color.White,
onSurface: Color = Color.White,
onError: Color = Color.Black
)
2
3
4
5
6
7
8
9
10
11
12
13
14
接着,我们来定义形状,代码如下:
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(8.dp),
large = RoundedCornerShape(16.dp)
)
2
3
4
5
我们根据不同大小的形状,设置不同的圆角,当然你也可以设置颜色、四个角的单独尺寸等。
接着,我们来定义排版,代码如下:
val Typography = Typography(
body1 = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
),
button = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 14.sp
),
)
2
3
4
5
6
7
8
9
10
11
12
13
我们只定义了body1
和button
,有兴趣的也可以试试其他的(感觉这属性没什么卵用)。
好,现在让我们用起来,我们添加如下代码:
@Composable
fun ComposeTourTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
// 根据不同模式使用不同颜色值
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
逻辑很简单,就只直接调用MaterialTheme
来传入我们定义的颜色、形状和排版,这里可以使用isSystemInDarkTheme()
来判断当前是否是深色模式,如果是深色模式,就使用深色主题,否则就用浅色主题。
最后,在Activity里面调用:
setContent {
ComposeTourTheme {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// 添加一个Card
Card(modifier = Modifier.padding(bottom = 16.dp)) {
// 在Card里面添加一个CheckBox,设置边距为32dp
Checkbox(checked = true, onCheckedChange = {}, modifier = Modifier.padding(32.dp))
}
// 添加一个Button
Button(onClick = { Toast.makeText(this@MainActivity, "click button", Toast.LENGTH_SHORT).show() }) {
Text(text = "Button")
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
很简单,我们添加一个Card(就是CardView),在Card里面添加一个CheckBox,然后添加一个Button。现在让我们来看看效果:
可以看到,切换了深色主题后,颜色会自动跟着改变,并且Card的背景圆角和Button的背景圆角也是不一样的,这是因为Card默认用的是medium尺寸,而Button默认用的是small尺寸。当然,其他属性你也可以自己去尝试。
一句话,主题就是在形状、颜色和排版方面,给app一个宏观的,粗粒度的统一,可以快速切换app的整体风格,当然,如果你要具体到每一个控件,那么主题是不适用的,你需要针对每个控件去对Modifier做具体定制,这里不再废话。