
目录
一、主题
借助 Jetpack Compose,您可以通过应用主题,轻松地赋予应用一致的外观和风格。您可以自定义 Compose 的 Material Design 实现,使其适合您产品的品牌。如果这不符合您的需求,您可以使用 Compose 的公共 API 构建自定义设计系统。
当我们使用Android Studio
创建一个Compose
应用时,默认给我们创建了一个ui.theme
包,包里面包含了Color.kt
、Shape.kt
、Theme.kt
、Type.kt
,而这刚好就是本文要讲到的主题。
下面,我们就跟着代码看一下:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeTheme {
MainPage()
}
}
}
}
复制代码
自动生成的MainActivity
中结构大概是这样的,那么这个ComposeTheme
是个什么东西呢?我们点进去看一下:
private val DarkColorPalette = darkColors()
private val LightColorPalette = lightColors()
@Composable
fun ComposeTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
MaterialTheme(
colors = colors,
typography = Typography,
shapes = Shapes,
content = content
)
}
复制代码
了然,在上面说到的Theme.kt
内,Android Studio
为我们生成了支持跟随系统常规与暗黑模式切换的主题。
MaterialTheme
是官方提供的一种主题实现,它由 由颜色、排版和形状属性组成。上面代码中的主题模式切换仅对颜色进行了处理。
1. 颜色(Colors)
那么接下来我们看看DarkColorPalette
和LightColorPalette
是什么?
private val DarkColorPalette = darkColors()
private val LightColorPalette = lightColors()
复制代码
继续查看 darkColors()
和 lightColors()
,以lightColors()
源码为例:
fun lightColors(
primary: Color = Color(0xFF6200EE),
primaryVariant: Color = Color(0xFF3700B3),
secondary: Color = Color(0xFF03DAC6),
secondaryVariant: Color = Color(0xFF018786),
background: Color = Color.White,
surface: Color = Color.White,
error: Color = Color(0xFFB00020),
onPrimary: Color = Color.White,
onSecondary: Color = Color.Black,
onBackground: Color = Color.Black,
onSurface: Color = Color.Black,
onError: Color = Color.White
): Colors = Colors(
primary,
primaryVariant,
secondary,
secondaryVariant,
background,
surface,
error,
onPrimary,
onSecondary,
onBackground,
onSurface,
onError,
true
)
复制代码
他们都继承自Colors
,并且在入参中对Colors
什么的颜色属性进行了默认值赋予。
可以得出结论:Compose
为我们默认提供了亮色模式和暗黑默认的两套Colors
配置,常规情况下,我们只需要将不同模式下的颜色属性改变为我们想要的颜色即可。
可是Compose
的Colors
只提供了12个颜色,不够用或者提供的描述不够明确怎么办?
这个时候Kotlin
的语法糖就极大的排上用上了,我们可以通过给Colors
添加拓展属性来定义我们想要的颜色属性,比如:
val White = Color(0xFFFFFFFF)
val Black = Color(0xFF000000)
val Colors.Divider: Color
@Composable get() = if (isLight) Black else White
Text(text = "RoundButton",color = MaterialTheme.colors.Divider)
复制代码
1.1. 值得一提
虽然 Material
是我们推荐的设计系统并且 Jetpack Compose
附带了 Material
的实现,但您并非只能使用它。您完全可以采用同样的方式创建自己的设计系统;Material
完全基于公共 API
,您可以使用这些 API
来实现此目的。
虽然官方附带了 Material
的实现,但是也仅仅局限于亮色和暗黑模式的切换,要通过Material
来实现各种主题,还是需要自定义的。
2. 排版(Typography)
我们来看看官方的描述
Compose
使用 Typography
、TextStyle
和字体相关类来实现字型系统。Typography
构造函数可以提供每种样式的默认值
Typography
是用来统一管理和控制字体大小、样式等属性的,官方一样为我们定义了若干个属性并赋予了默认值:
@Immutable
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
) {
...
}
复制代码
通过TextStyle
我们可以定义字体大小、样式、字重等多种属性:
@Immutable
class TextStyle(
val color: Color = Color.Unspecified,
val fontSize: TextUnit = TextUnit.Unspecified,
val fontWeight: FontWeight? = null,
val fontStyle: FontStyle? = null,
val fontSynthesis: FontSynthesis? = null,
val fontFamily: FontFamily? = null,
val fontFeatureSettings: String? = null,
val letterSpacing: TextUnit = TextUnit.Unspecified,
val baselineShift: BaselineShift? = null,
val textGeometricTransform: TextGeometricTransform? = null,
val localeList: LocaleList? = null,
val background: Color = Color.Unspecified,
val textDecoration: TextDecoration? = null,
val shadow: Shadow? = null,
val textAlign: TextAlign? = null,
val textDirection: TextDirection? = null,
val lineHeight: TextUnit = TextUnit.Unspecified,
val textIndent: TextIndent? = null
)
复制代码
想想XML中的TextStyle
那寥寥的几个属性:
终于不再为了UI要求的各种字重而使用画笔来加粗文字了,喜大普奔
同样,我们依旧可以通过为Typography
添加拓展属性来定义我们自己的排版
val Typography.Title: TextStyle
@Composable get() = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Bold,
fontSize = 18.sp
)
val Typography.SubText: TextStyle
@Composable get() = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 16.sp
)
val Typography.Content: TextStyle
@Composable get() = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp
)
val Typography.Description: TextStyle
@Composable get() = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 14.sp
)
复制代码
Column(
Modifier
.background(Color.White)
.padding(20.dp)) {
Text(text = "Title",style = MaterialTheme.typography.Title)
Text(text = "SubText",style = MaterialTheme.typography.SubText)
Text(text = "Content",style = MaterialTheme.typography.Content)
Text(text = "Description",style = MaterialTheme.typography.Description)
}
复制代码
效果如下:

3. 形状(Shapes)
Material 定义了一个形状系统,可让您定义大型、中型和小型组件的形状。
与 Colors
、 Typography
一样,官方为我们提供了Shapes
用来管理项目中使用到样式。
依旧来看看Shapes
的源码:
@Immutable
class Shapes(
val small: CornerBasedShape = RoundedCornerShape(4.dp),
val medium: CornerBasedShape = RoundedCornerShape(4.dp),
val large: CornerBasedShape = RoundedCornerShape(0.dp)
) {
...
}
复制代码
正如官方文档所说,Shapes
提供了大、中、小三种形状配置,以便在同一语义下为不同大小的组件提供不同的样式;如果大、中、小满足不了你的需求,依旧可以给Shapes
添加拓展属性来满足需求。
不过我认为Shapes
在日常开发中意义不大,在编写页面时,直接在组件内使用各种Shape
就好了,比如下面代码中
Shape
的使用。
@Composable
fun RoundButton() {
Box(
modifier = Modifier
.width(300.dp)
.height(90.dp)
.padding(20.dp)
.background(Color(0xFF3ADF00), shape = RoundedCornerShape(50)),
contentAlignment = Alignment.Center){
Text(text = "RoundButton",color = Color.White)
}
}
复制代码
Compose
中shape
有如下4个子类:
3.1. RoundedCornerShape
直接看效果RoundedCornerShape(50)

3.2. CutCornerShape
直接看效果CutCornerShape(50)

3.3. AbsoluteRoundedCornerShape
AbsoluteRoundedCornerShape
和RoundedCornerShape
差不多,官方的描述是:
描述带有圆角的矩形的形状。
此形状不会自动镜像 中的角大小LayoutDirection.Rtl
,RoundedCornerShape
用于此形状的布局方向感知版本。
3.4. AbsoluteCutCornerShape
AbsoluteCutCornerShape
和CutCornerShape
差不多,官方的描述是:
描述带有切角的矩形的形状。角尺寸代表切割长度 - 切割直角三角形的两条腿的大小。
此形状不会自动镜像 中的角大小LayoutDirection.Rtl
,CutCornerShape
用于此形状的布局方向感知版本。
二、最后
好记性不如烂笔头,初识 Jetpack Compose
系列是我自己的学习笔记,在加深知识巩固的同时,也可以锻炼一下写作技能。文章中的内容仅作参考,如有问题请留言指正。
1. 参考