一、什么是Compose?
Jetpack Compose 是Google新推出的用于构建原生 Android 界面的新工具包。它可简化并加快 Android 上的界面开发,使用更少的代码、强大的工具和直观的Kotlin API,快速让应用生动而精彩。
二、Compose的优势
-
更少的代码
在Android View系统,实现一个功能需要有XML和Kotlin/Java两部分,而在Compose中不需要拆分两部分,所有代码都使用同一种语言编写并且位于同一个文件中
,往往复杂的功能几行代码就能搞定,因此Compose编写的代码简洁且易于维护。
如:实现一个列表,简单几行代码
@Composable
fun Conversation(messages:List<Message>){
LazyColumn {
items(messages){ message->
MessageCard(message)
}
}
}
直观
Compose使用声明性API,意味着只需描述界面,Compose会负责完成其余工作,应用状态发生变化时,界面会自动智能刷新。加快应用开发
Compose兼容现有的所有代码,方便随时随地开始采用。借助全面的Android Studio支持和实时预览功能,可以更快的迭代。功能强大
凭借对Android平台API的直接访问和对于Material Design、深色主题、动画等的内置支持,创建精美的应用。
三、开发环境准备
IDE版本:Android Studio Arctic Fox
语言:Kotlin
创建支持Jetpack Compose的新应用
打开Android Studio,依次执行File > New > New Project,在弹出的New Project弹窗中选择Empty Compose Activity,然后点击Next,设置对应Name、PackageName、和保存位置等信息,直接点击【Finish】即可完成Compose工程创建。
注:
1.仅支持Kotlin。
2.工程创建后会自动引入Compose相关基础库,如需其他工具包可在项目的Build.gradle配置。
四、Compose可组合函数和预览
新的Compose工程创建好后,在体验Compose开发前我们先来了解两个非常关键的注解。
★ 可组合函数
Jetpack Compose 是围绕可组合函数构建的。这些函数可让您以程序化方式定义应用的界面,只需描述应用界面的外观并提供数据依赖项,而不必关注界面的构建过程(初始化元素,将其附加到父项等)。如需创建可组合函数,只需将 @Composable
注解添加到函数名称中即可。
@Composable
fun MessageCard(name: String) {
Text(text = "Hello $name!")
}
★ 预览函数
Android Studio允许在IDE中预览可组合函数,无需将应用安装到设备上。使用到的关键注解@Preview
@Preview
@Composable
fun DefaultPreview() {
MessageCard("Android")
}
五、布局
界面元素采用多层次布局,元素中包含其他元素。Compose中通过一个可组合函数调用其他可组合函数来构建界面。
-
添加文本
使用可组合函数Text
添加一个文本
@Composable
fun MessageCard(msg: Message) {
Text(text = msg.author)
}
-
使用Column和Row
针对多个元素时,怎么布局呢?此时就要用到Column和Row函数了。
Column
函数可以让元素垂直排列。Row
函数可使元素水平排列。
@Composable
fun MessageCard(message:Message) {
//行
Row {
//添加一个图片元素
Image(
//填充内容
painter = painterResource(id = R.mipmap.ic_girl),
contentDescription = "logo",
)
//列
Column{
Text(text = message.author)
Text(text = message.body)
}
}
}
-
添加图片元素
添加图片元素采用的可组合函数为:Image
,见上例子。 -
使用修饰符配置布局
在Compose中元素提供了修饰符,通过设置元素的modifier
,可以更改元素的大小、布局、外观、互动。
如下例子中,给Image增加修饰符
//添加一个图片
Image(
//填充内容
painter = painterResource(id = R.mipmap.ic_girl),
contentDescription = "logo",
//尺寸及形状
modifier= Modifier
.padding(top = 2.dp)
.size(40.dp) //图像尺寸
.clip(CircleShape) //裁剪形状
)
六、使用Material Design
Compose的许多界面元素都支持Material Design。
创建的项目中会生成默认主题,支持自定义MaterialTheme。
-
设置一个Material主题样式
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { //设置主题 JetpackDemoTheme { ...... } } }
-
使用主题颜色
以为图片添加圆形边框为例://添加一个图片 Image( //填充内容 painter = painterResource(id = R.mipmap.ic_girl), contentDescription = "logo", //尺寸及形状 modifier= Modifier .padding(top = 2.dp) .size(40.dp) //图像尺寸 .clip(CircleShape) //形状 .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)//边框样式 )
-
排版
MaterialTheme 中提供了 Material 排版样式,只需将其添加到 Text 可组合项中即可。Text( text = message.author, color = MaterialTheme.colors.secondaryVariant, //添加MaterialTheme排版 style = MaterialTheme.typography.subtitle2 )
-
设置边框形状
//设置一个边框 Surface(shape = MaterialTheme.shapes.medium, elevation = 2.dp, color = surfaceColor, modifier = Modifier.animateContentSize().padding(1.dp).clickable { isExpanded = !isExpanded } ){ Text(text = msg.body) }
-
启用深色主题
开发过程中,预览支持启用深色主题(即夜间模式),Jetpack Compose默认能处理深色主题。使用Material颜色、文本和背景时,系统会自动适应深色背景。
启用方式如下:@Preview(name = "Light Mode")//白天模式 @Preview(showBackground = true,uiMode = Configuration.UI_MODE_NIGHT_YES,name = "Dark Mode")//夜间模式 @Composable fun DefaultPreview() { JetpackDemoTheme { MessageCard(Message("Android","Jetpack Compose")) } }
七、列表和动画
在实际应用中列表和动画非常常见,这里以简单学习如何利用Compose轻松创建列表和添加动画效果。
-
创建消息列表
Compose为我们提供了LazyColumn
和LazyRow
可组合函数,分别对应垂直列表和水平列表。@Composable fun Conversation(messages:List<Message>){ //垂直方向列表 LazyColumn { items(messages){ message-> MessageCard(message) } } } //定义数据类 data class Message(val author: String, val body: String)
静态列表图:
-
在展开消息时显示动画效果
首先将Text的行数设置为一行,当点击时再全部展开。
先使用可组合函数remember
记录没行的展开状态,保存在mutableStateOf
中,该值更新后,系统会自动智能重新绘制使用此状态的元素,这一过程又被称为重组
。@Composable fun MessageCard(message:Message) { ... var isExpanded by remember { mutableStateOf(false) } ... }
现在可以通过点击消息更改这个
isExpanded
变量值,然后根据这个值来修改消息的背景和工行效果。@Composable fun MessageCard(message:Message) { ... val surfaceColor: Color by animateColorAsState( if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface, ) Column{ ... //设置一个边框 Surface(shape = MaterialTheme.shapes.medium, elevation = 2.dp, color = surfaceColor, modifier = Modifier.animateContentSize() .padding(1.dp) //1.添加一个可点击事件 .clickable { isExpanded = !isExpanded } ){ Text( text = message.body, modifier = Modifier.padding(all = 4.dp), //2.展开时设置行数 maxLines=if (isExpanded) Int.MAX_VALUE else 1, //添加MaterialTheme排版 style = MaterialTheme.typography.body2 ) } ... } ... }
最后上一张带展开收起动画的gif效果图
最后附上源码地址