> 文章列表 > Jetpack Compose之线性布局和帧布局

Jetpack Compose之线性布局和帧布局

Jetpack Compose之线性布局和帧布局

概述

Compose 中的线性布局对应的是Android传统视图中的LinearLayout,不一样的地方是,Compose根据Orientation的不同又将布局分为Column和Row, Column对应传统视图LinearLayout中orientation = “vertical”的情况,Row对应传统视图LinearLayout中orientation = “horizontal”的情况.由于两者内部元素在父容器中的布局和对其方式不同,分成两个组件有助于提供类型安全的Modifier修饰符。而Compose中的帧布局对应的是Android传统View中的FrameLayout,它可以让自己的子组件依次按照顺序推叠。

实例解析

1.线性布局

在Compose中,线性布局根据使用场景的不同,分为Column和Row,Column 是垂直线性布局组件,Row是水平线性布局组件

1.1 Column组件

@Composable
inline fun Column(modifier: Modifier = Modifier,verticalArrangement: Arrangement.Vertical = Arrangement.Top,horizontalAlignment: Alignment.Horizontal = Alignment.Start,content: @Composable ColumnScope.() -> Unit
)

上面是Column的参数列表,其中verticalArrangement和horizontalAlignment参数分别可以帮助我们安排子项的垂直/水平位置,在默认情况下,子项会以垂直方向靠上(Arrangment.Top)、水平方向靠左来布置子项的摆放

我们可以以一个例子看下Column的使用

@Composable
fun LinearLayoutDemo() {Column(modifier = Modifier.border(1.dp, color = Color.Red).size(150.dp),verticalArrangement = Arrangement.Center) {Text(text = "Hello World",style = MaterialTheme.typography.h6,modifier = Modifier.align(Alignment.CenterHorizontally))Text(text = "JetPack",style = MaterialTheme.typography.h6,modifier = Modifier.align(Alignment.CenterHorizontally))Text(text = "zhongxj",style = MaterialTheme.typography.h6,modifier = Modifier.align(Alignment.CenterHorizontally))}
}

运行结果:
Jetpack Compose之线性布局和帧布局

在上面的代码中,我们通过verticalArrangement参数,将Column中的Text摆放到了组件的中间,然后使用Modifier.align修饰符来独立设置子项的对齐规则
这里可能有人会问,不是有horizontalAlignment参数吗,水平方向为啥还要用Modifier.align呢?因为对于垂直布局中的子项,Modifier.align只能设置自己在水平方向的位置,反之水平布局的子项,只能设置自己在垂直方向的位置,就比如我们正在介绍的Column组件,当Column组件中有多个子项时,他们在垂直方向永远是线性排列的,如果允许子项被单独设置,就会出现不好的情况,比如Column中有A,B,C三项,如果配置A的对齐方向是Aligment.Bottom,B为Aligment.Top,这显然是无法实现的,所以Column的子项在垂直方向布局只能通过verticalArragnment进行整体设置。(注意:这里不是说Column只能使用verticalArragnment参数)

注意:在不给Column指定高度、宽度、大小的情况下,Column组件会默认包裹里面的子项,在这个时候我们是无法使用Column参数中的verticalArrangement或者horizontalAlignment来定位子项在Column中的整体位置的

1.2 Row组件

Row组件可以将内部子项按照从左到右的方向水平排列,和Cloumn组件配合使用就可以构建出很丰富美观的界面。下面是一个使用Row组件和Column组件制作的文章卡片,代码如下:

@Composable
fun ArticleCard() {Surface(shape = RoundedCornerShape(8.dp),modifier = Modifier.padding(horizontal = 12.dp).fillMaxWidth(),elevation = 10.dp,) {Surface(modifier = Modifier.padding(12.dp), color = Color(0xeeeeeeee)) {Column(modifier = Modifier.padding(12.dp)) {Text(text = "JetPack Compose",style = MaterialTheme.typography.h6)Spacer(modifier = Modifier.padding(vertical = 5.dp))Text(text = " Jetpack Compose是第一个使用Kotlin正在开发中的大型项目," +"因此Android团队正在探索Kotlin API指南的新世界,以创建一组特定于Compose API的指南," +"该工作仍在进行中,仍然有很长的路要")Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween) {IconButton(onClick = { /*TODO*/ }) {Icon(imageVector = Icons.Filled.Favorite,contentDescription = null, modifier = Modifier.size(16.dp))}IconButton(onClick = { /*TODO*/ }) {Icon(painterResource(id = R.drawable.comment),contentDescription = null, modifier = Modifier.size(16.dp))}IconButton(onClick = { /*TODO*/ }) {Icon(painterResource(id = R.drawable.share),contentDescription = null, modifier = Modifier.size(16.dp))}}}}}
}

运行结果:
Jetpack Compose之线性布局和帧布局

从上面的代码中可知,Row的horizontalArrangement参数帮助我们合理配置了按钮的水平位置。可以看到,图标部分,喜欢和分享按钮呈左右两端对齐,Arrangement定义了很多子项对齐的方式,除了Center(居中),Start(水平靠左),End(水平靠右)等常见的对齐方式,还有一些特定场景下的对齐方式,如Space Between,Space Evenly等。

2.帧布局

2.1 Box组件

Box组件是一个能够将里面的子项依次按照顺序堆叠的布局组件,在使用上类似于传统布局的FrameLayout,这个很简单,我们看下一段代码了解下它的使用。

@Composable
fun BoxDemo(){Box(modifier = Modifier.size(150.dp).background(Color.Green))Box(modifier = Modifier.size(80.dp).background(Color.Red))Text(text = "Hello World")
}

运行结果:
Jetpack Compose之线性布局和帧布局

2.2 Surface组件

Surface从字面上理解是一个平面,在Material Design设计准则中也同样如此,我们可以将很多的组件摆放在这个平台之上,可以设置这个平面的边框,圆角,颜色等.例如,使用Surface实现一个卡片效果,代码如下:

@Composable
fun SurfaceDemo() {Surface(shape = RoundedCornerShape(8.dp),elevation = 10.dp,modifier = Modifier.width(300.dp).height(100.dp),color = Color.Gray) {Row(modifier = Modifier.clickable {}) {Image(painter = painterResource(id = R.drawable.portrait),contentDescription = null,modifier = Modifier.size(100.dp),contentScale = ContentScale.Crop)Spacer(modifier = Modifier.padding(horizontal = 12.dp))Column(modifier = Modifier.fillMaxHeight(),verticalArrangement = Arrangement.Center) {Text(text = "zhongxj", style = MaterialTheme.typography.h6)Spacer(modifier = Modifier.padding(vertical = 8.dp))Text(text = "海塔灯")}}}
}

运行结果:
Jetpack Compose之线性布局和帧布局

从上面的代码中我们可以看到,在Surface中我们主要编写UI代码,而Surface主要负责整个组件的形状,阴影,背景等,Surface可以帮助我们解耦一些代码,而不必在单个组件上添加很多的Modifier修饰符方法。

很多读者可能会有疑问有了Box为啥还要加一个Surface组件,其实Box和Surface组件还是有区别的,如果我们需要快速设置界面的形状,阴影,边框,颜色等,我们使用Surface会更好,因为这样可以减少Modifier的使用量。而如果我们只是需要简单设置界面背景颜色,大小,且需要简单布局下子项的位置,则可以使用Box

3.Spacer留白

在很多时候,我们需要让组件之间留有空白的间隙,这时候就可以使用Compose提供的Spacer组件,简单用一个demo展示Spacer的使用。

@Composable
fun SpacerDemo(){Row {Box(modifier = Modifier.size(100.dp).background(Color.Green))Spacer(modifier = Modifier.width(20.dp))Box(modifier = Modifier.size(100.dp).background(Color.Yellow))Spacer(modifier = Modifier.weight(1f))Box(modifier = Modifier.size(100.dp).background(Color.Magenta))}
}

运行结果
Jetpack Compose之线性布局和帧布局

从上面的代码中可以看出Spacer的另一种使用场景,那就是在代码中使用Box绘制占位的矩形块在没有内容的时候完成可以使用Spacer来替代。

总结

本文主要讲了线性布局和帧布局在Compose中如何使用,其实非常简单,就需要我们多加练习,没有啥技巧。等啥时候我们写Compose的UI和写XML的UI一样熟练的时候,我们的工作效率就会大大的提升,可以用更少的代码实现更炫的UI效果,而且Kotlin和Java还可以混合使用,现在我已经在用Compose写测试的界面了,非常方便,推荐读者也动起来,使用Java的小伙伴可以使用Compose写界面,Java写功能,而使用Kotlin的小伙伴,则可以更方便的使用Compose,一种语言,完成界面和功能,真的特别酷。