目录
- 初识 Jetpack Compose(一) :Hello,Jetpack Compose!
- 初识 Jetpack Compose(二) :布局
- 初识 Jetpack Compose(三) :修饰符(Modifier)
- 初识 Jetpack Compose(四) :主题
- 初识 Jetpack Compose(五) :组件-Text
一、主题
借助 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
) {
//根据系统主题模式指定colors的值
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
)
//使用自定义的Typography属性
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(
/**
* Shape used by small components like [Button] or [Snackbar]. Components like
* [FloatingActionButton], [ExtendedFloatingActionButton] use this shape, but override
* the corner size to be 50%. [TextField] uses this shape with overriding the bottom corners
* to zero.
*/
val small: CornerBasedShape = RoundedCornerShape(4.dp),
/**
* Shape used by medium components like [Card] or [AlertDialog].
*/
val medium: CornerBasedShape = RoundedCornerShape(4.dp),
/**
* Shape used by large components like [ModalDrawer] or [ModalBottomSheetLayout].
*/
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 系列是我自己的学习笔记,在加深知识巩固的同时,也可以锻炼一下写作技能。文章中的内容仅作参考,如有问题请留言指正。