最近一直在准备软考,天天在看教学视频,这不后天就要考试了,我报的是软件设计师,说说我对软考的理解吧,软考高级我不知道,就中级而言,非常符合中国的应试性教育。考的都很广,但没有一样东西考的精,我学了那么长时间,知识储备已经有了,考试应付足够了,但我觉得我可能永远没有机会把这些只是应用到实际中。扯多了,回归正题。
我第一次听说compose是在逛Android大牛讲堂的时候,大佬说这会成为以后UI的主流框架,就很好奇到底是什么样的东西能够动摇xml那么多年的老大哥位置,还一直被谷歌力推,下面就让我们来一步步走近它。
参看文章:Android开发者平台
什么是compose
先看官方的解释:
Jetpack Compose 是一个适用于 Android 的新式声明性界面工具包。Compose 提供声明性 API,让您可在不以命令方式改变前端视图的情况下呈现应用界面,从而使编写和维护应用界面变得更加容易。此术语需要一些解释说明,它的含义对应用设计非常重要。
这里我就官方解释给出自己的理解,不以命令方式改变前端视图来呈现应用界面,其实就是叫我们摒弃命令式UI,来使用Compose这种声明式UI。那为什么要这样做呢?
我们的传统式UI在绘制界面上都是重新生成整个视图,如果我们从服务器拿到一条数据需要适配给多个视图,那更新起来会很麻烦,甚至出现忘记去更改数据的情况,Compose可以避免这种情况,当然,这是后话了。还有一个原因是传统命令式UI需要重新绘制视图,从头到尾重新渲染,这会导致消耗资源大,速度慢,而Compose做的只是在概念上从头开始重新生成整个屏幕,实际上只执行必要的更改。这就是他相比较于xml的优势所在。
compose的简单使用
Compose的使用需要下载Android studio的Fox及以上版本,然后new一个compose的新工程,选择Empty Compose Activity
基本代码如下:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeDemo2Theme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemo2Theme {
Greeting("Android")
}
}
我们可以看到很多不一样的东西,首先看到两个注解@compose和@Preview,@compose注解表示此注释可告知 Compose 编译器:此函数旨在将数据转换为界面。也就是说带有@conpose注解的函数都是编写界面的函数,通常我们叫它可组合函数。
对于@Preview注解看看官方的解释:
Android Studio 允许您在 IDE 中预览可组合函数,无需将应用安装到 Android 设备或模拟器中。可组合函数必须为任何参数提供默认值。因此,您无法直接预览 MessageCard()
函数,而是需要创建另一个名为 PreviewMessageCard()
的函数,由该函数使用适当的参数调用 MessageCard()
。请在 @Composable
上方添加 @Preview
注解。
就是@Preview注解的函数编写的界面会展示在预览区中。和实际效果不一定相同。
比如上述代码改成
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeDemo2Theme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
Greeting("蒙奇.D.路飞")
}
}
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemo2Theme {
Greeting("Android")
}
}
我们可以看到在setContent中调用的和在预览函数中调用的Greeting函数传的参数不一样,所以预览视图和实际运行界面也不一样
预览视图:
实际界面截图:
那要怎么让他们统一呢,很简单,我们只需要在setContent里面也调用预览函数就可以了,如下:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DefaultPreview()
}
}
}
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemo2Theme {
Greeting("蒙奇.D.路飞")
}
}
这样预览效果和实际效果就是一样的了。
compose实现简单布局
我们以官方给出的简单demo为例:比如我们要创建这样一个视图:
首先在布局里面添加三个文本:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DefaultPreview()
}
}
}
@Composable
fun message(name: String, othername: String, phone: Long) {
Text(text = "绰号:$othername", fontSize = 14.sp)
Text(text = "电话号码:$phone", fontSize = 14.sp)
Text(text = "姓名: $name!", fontSize = 14.sp)
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
message(name = "张志平", othername = "大帅比", phone = 110)
}
}
效果如图所示:
我们会发现重叠在了一起,这时候使用Cloumn可以使他们竖直排序
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DefaultPreview()
}
}
}
@Composable
fun message(name: String, othername: String, phone: Long) {
Column {
Text(text = "绰号:$othername", fontSize = 14.sp)
Text(text = "电话号码:$phone", fontSize = 14.sp)
Text(text = "姓名: $name!", fontSize = 14.sp)
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
message(name = "张志平", othername = "大帅比", phone = 110)
}
}
如图:
接下来添加图片,图片与文字水平,使用Row
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DefaultPreview()
}
}
}
@Composable
fun message(name: String, othername: String, phone: Long) {
Column {
Text(text = "绰号:$othername", fontSize = 14.sp)
Text(text = "电话号码:$phone", fontSize = 14.sp)
Text(text = "姓名: $name!", fontSize = 14.sp)
}
}
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
ComposeDemoTheme {
Row(modifier = Modifier.padding(all = 8.dp)) {
Image(
painter = painterResource(id = R.drawable.tx),
contentDescription = "联系人照片",
modifier = Modifier
.size(60.dp)
.scale(1.0F),
contentScale = ContentScale.FillBounds
)
Spacer(modifier = Modifier.width(8.dp))
message(name = "张志平", othername = "大帅比", phone = 110)
}
}
}
图片如图所示:
到此,一个compose的简单例子就完成了,可能里面有些方法和写法大家会觉得很不熟悉,建议点进去看一下源码,我也是看着源码写的,源码的注释已经很清楚了,不会看的兄弟们一定要学着去看,其实很简单,不要自己把自己劝退,比如Image()里面的构造参数,怎么调大小,怎么调比例,都是在源码里面可以找到的,后续我会逐渐深入地去了解它,也会写出文章和大家交流。