注册

Jetpack Compose 初体验(一)

你是否受够了 Android 中 UI 编写的体验——在 xml 文件中编写复杂的层级结构和繁多的属性,动态化的视图逻辑又被分裂到 Activity 中?哦,这该死的友好度和割裂感!


这两年,Flutter 大行其道,不论是网上的讨论度还是实际的落地项目,风头一时无两。所以从这个角度来说,作为 UI 框架的 Flutter,无疑是成功的。本着借鉴的思想(或许吧,谁知道呢),Android 在 Jetpack 项目中新增了一套全新的视图开发套件——Compose。它有着和 Flutter 一样好看的(姑且这么认为吧)外表,但究竟只是一个好看的花瓶还是才貌双全,这得我们自己去寻找答案。


Compose 当前还处于测试版本,想要使用它,我们需要首先下载 Android studio 的 canary 版本以提供支持。你可以在这里下载或者在你现有的 Android studio 中打开 File -> Settings -> Appearance & Behavior -> System Settings -> Updates 菜单,然后切换到 canary 渠道再点击 Check Now 按钮即可更新到最新的 canary 版本。


一、布局


1.可组合函数


使用 Compose 创建一个界面是简单的,只需通过 @Composable 注解定义一个可组合函数,在函数中返回界面元素组件即可。


@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
复制代码

该函数可以接收参数。函数内可以是一个组件,也可以是多个组件的组合。


通过 setContent 方法块可以设置页面内容,类似于之前的 setContentView() 方法。


setContent {
Text(text = "Hello Compose!")
}
复制代码

相比于之前的界面书写过程,Compose 更「神奇」的一个体现在于它可以直接在 Android studio 中预览我们编写的界面和组件,而无需让程序运行在设备中。


我们只需要在可组合函数的基础上再新增一个 @Preview 注解,但是需要注意的是,预览函数不接受参数,所以比较好的做法是在可组合函数的基础上编写其对应的预览函数。


@Preview
@Composable
fun DefaultPreview() {
Greeting("Android")
}
复制代码

预览函数对你的应用在设备上的最终呈现不会产生影响,Android studio 提供了一个预览窗口可以实时看到预览函数所呈现的效果。


image-20210412225335487.png


2.布局


我们编写的应用界面几乎任何时候都不会是简简单单的单一的控件,而是一定数量的独立控件在空间上的一种组合。


首先,我们就盲猜,如果我想竖直方向排列三个文字组件,肯定不是像下面这样随便组合三个 Text 控件。它怎么可能那么聪明,能知道你是想横着排还是竖着排,想并排排还是旋转开。怎么可能有人比苏菲更懂你!


@Composable
fun VerticalText() {
Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
复制代码

image-20210413003422129.png


那,就组合喽。


@Composable
fun VerticalText() {
Column {
Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
}
复制代码

给三个 Text 约定个竖框框,它们就能乖乖地排起队。


image-20210413005809783.png


这里,悄摸摸地说一句,这要是没有偷瞄 Flutter 的考卷 向优秀的思想借鉴,我把三个 Text 布局在我脑门上!


当然,只有这么生硬的排列可不行,我们还需要加点属性,使得整个布局更和谐点——例如,加点边距。


我们希望给 Column 加一个内边距,那么我们就应该给 Column 添加一个属性。Modifier 类用来给组件添加装饰或者行为,如背景、边距、点击事件等。


@Preview(showBackground = true)
@Composable
fun VerticalText() {
Column(
modifier = Modifier.padding(16.dp)
) {
Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
}
复制代码

image-20210413210728702.png


现在,为了让界面看起来不那么单调,我们给这个界面加上下面这一张图片。


![](Compose 初体验.assets/hello_world_new_black.png)


将这张图片拷贝到 drawable 资源文件夹下面,然后通过下面的方式引用。


@Preview(showBackground = true)
@Composable
fun VerticalText() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(id = R.drawable.hello_world_new_black),
contentDescription = null
)
Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
}
复制代码

Image 的其中一个构造函数支持以下参数,其中 painter 参数和 contentDescription 参数没有默认值,为必传参数。


image-20210420220142848.png


这样,图片就被构造出来啦,看一下效果:


image-20210420220432840.png


那怎么该对图片进行一些约束呢?作为一个头图,我不希望它这么哗众取宠,做图片要低调一点。


在上面,我们认识了 Modifier,那就寻求它的帮助,让我们的图片小一些吧。


Image(
painter = painterResource(id = R.drawable.hello_world_new_black),
contentDescription = null,
modifier = Modifier
.width(126.dp)
.height(62.dp),
contentScale = ContentScale.Inside
)
复制代码

借助 Modifier 将图片的高度和宽度分别进行限定。然后通过 contentScale 参数对图片的缩放方式进行约束。ContentScale.Inside 保持图片比例不变的情况下尽可能地充满父控件的体积。


把上面的 Image 放入 preview 方法,看一下效果:


image-20210420221651702.png


现在头图就被我们拿捏得死死的,但是它还不是很好看,没脖子,加个脖子。


@Preview(showBackground = true)
@Composable
fun VerticalText() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(id = R.drawable.hello_world_new_black),
contentDescription = null,
modifier = Modifier
.width(126.dp)
.height(62.dp),
contentScale = ContentScale.Inside
)

Spacer(modifier = Modifier.height(16.dp))

Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
}
复制代码

image-20210420222219906.png


这样是不是好看多了,嗯,是的。


3.Material Design


谷歌霸霸的产品当然是支持 Material Design 的,那咱就看看。


做头图不要锋芒毕露,做图处事要圆滑一点。给头图加个圆角是个不错的想法。


在 Android 传统的 UI 编写中,圆角图片一直没有很简单的解决方案,需要通过诸如自定义 ImageView 的方式来实现。但是,朋友们,当你使用 Compose 框架的时候,只需要一行代码就可以圆角图片的显示!家祭无忘告乃翁。


@Preview(showBackground = true)
@Composable
fun VerticalText() {
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(id = R.drawable.hello_world_new_black),
contentDescription = null,
modifier = Modifier
.width(126.dp)
.height(62.dp)
.clip(shape = RoundedCornerShape(4.dp)),
contentScale = ContentScale.Inside
)

Spacer(modifier = Modifier.height(16.dp))

Text("Hello World!")
Text("Hello Again World!")
Text("How old are you, World!")
}
}
复制代码

这里还是通过 Modifier 来实现需求,怎么样,现在的头图是不是圆滑可爱了很多。


image-20210420223334597.png


头图这么求上进,文字也不能落后,一篇好的文章要主次分明,错落有致。


声明 Typography 对象,然后给 Text 添加 style 属性,来控制文字的样式。


@Preview(showBackground = true)
@Composable
fun VerticalText() {
val typography = MaterialTheme.typography
Column(
modifier = Modifier.padding(16.dp)
) {
Image(
painter = painterResource(id = R.drawable.hello_world_new_black),
contentDescription = null,
modifier = Modifier
.width(126.dp)
.height(62.dp)
.clip(shape = RoundedCornerShape(4.dp)),
contentScale = ContentScale.Inside
)

Spacer(modifier = Modifier.height(16.dp))

Text("Hello World!", style = typography.h3)
Text("Hello Again World!", style = typography.body1)
Text("How old are you, World!", style = typography.body2)
}
}
复制代码

Typography 提供如下预设属性,囊括标题、子标题、段落体、按钮等。


image-20210420225524291.png


最终效果如下:


image-20210420225406851.png


怎么样,是不是主次开始变得分明了?结构变得清晰了?情节展开得顺滑了?故事开始自然了?……


当然,其他的诸如最大行数、字体、对齐方式等都可以被配置。


作者:Sandfone
链接:https://juejin.cn/post/6958979036181692424
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册