作者:海塔灯

概述

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)

)

}

}

运行结果:

在上面的代码中,我们通过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)

)

}

}

}

}

}

}

运行结果:

从上面的代码中可知,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")

}

运行结果:

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 = "海塔灯")

}

}

}

}

运行结果:

从上面的代码中我们可以看到,在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))

}

}

运行结果

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

总结

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

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89 Android 车载篇:https://qr18.cn/F05ZCM Android Framework底层原理篇:https://qr18.cn/AQpN4J Android 音视频篇:https://qr18.cn/Ei3VPD Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp Kotlin 篇:https://qr18.cn/CdjtAF Gradle 篇:https://qr18.cn/DzrmMB OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD Flutter 篇:https://qr18.cn/DIvKma Android 八大知识体:https://qr18.cn/CyxarU Android 核心笔记:https://qr21.cn/CaZQLo Android 往年面试题锦:https://qr18.cn/CKV8OZ 2023年最新Android 面试题集https://qr18.cn/CgxrRy Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ 音视频面试题锦:https://qr18.cn/AcV6Ap

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: