3、布局基础:Column、Row、Box 三大布局组件、Modifier 的概念与链式调用
各位同学,欢迎来到第三章。这一章我们聊聊 Compose 里最基础、也最核心的东西——布局。
说实话,我刚开始从传统 View 系统转到 Compose 时,最不适应的就是布局方式。以前写 XML,LinearLayout、RelativeLayout、FrameLayout 用得很顺手。到了 Compose 这边,变成了 Column、Row、Box。名字变了,但核心思想其实更简单了。
这一章我会带你彻底搞懂这三个组件,以及那个无处不在的 Modifier。嗯,Modifier 这东西,我第一次看的时候觉得它像个「魔法棒」,后来才发现它其实就是个链式调用的工具。咱们一步步来。
3.1 三大布局组件:Column、Row、Box
先看一张图,帮你快速建立整体认知:
这张图很直观。Column 是垂直堆叠,Row 是水平排列,Box 是层叠(像 FrameLayout)。记住这三个方向,你就能搭出任何界面。
3.2 Column:垂直布局
Column 就是把子组件从上往下排。我在项目中用得最多的是列表页面的整体骨架,比如用户信息页:头像在上,名字在中间,按钮在下面。
@Composable
fun UserProfile() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 头像
Icon(
imageVector = Icons.Default.Person,
contentDescription = "头像",
modifier = Modifier.size(80.dp),
tint = MaterialTheme.colorScheme.primary
)
// 名字
Text(text = "张三", style = MaterialTheme.typography.headlineSmall)
// 按钮
Button(onClick = { /* 编辑资料 */ }) {
Text("编辑资料")
}
}
}
这里有两个参数要注意:
- horizontalAlignment:控制子组件在水平方向的对齐方式。默认是 Start(左对齐),常用 CenterHorizontally(居中)。
- verticalArrangement:控制子组件在垂直方向的排列方式。spacedBy(12.dp) 表示每个子组件之间间隔 12dp。
3.3 Row:水平布局
Row 和 Column 是对称的。一个水平排,一个垂直排。参数也几乎一样,只是方向不同。
我记得有一次做底部操作栏,三个按钮要水平均匀分布。用 Row 配合 Arrangement.SpaceEvenly,几行代码就搞定了。
@Composable
fun BottomActions() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { /* 点赞 */ }) {
Icon(Icons.Default.ThumbUp, contentDescription = "点赞")
}
IconButton(onClick = { /* 评论 */ }) {
Icon(Icons.Default.Chat, contentDescription = "评论")
}
IconButton(onClick = { /* 分享 */ }) {
Icon(Icons.Default.Share, contentDescription = "分享")
}
}
}
Arrangement 有几种常用模式:
| 模式 | 效果 |
|---|---|
| Start | 从起始位置开始排列 |
| End | 从结束位置开始排列 |
| Center | 居中排列 |
| SpaceBetween | 首尾贴边,中间均匀分布 |
| SpaceEvenly | 所有间距(包括首尾)相等 |
| SpaceAround | 每个元素两侧间距相等,首尾间距为一半 |
3.4 Box:层叠布局
Box 允许子组件在 Z 轴方向叠加。说白了,就是后面的组件可以盖在前面的组件上面。
我经常用 Box 做「徽标」效果——比如一个头像右上角加个小红点。或者做「遮罩层」——图片上面盖一层半透明文字。
@Composable
fun AvatarWithBadge() {
Box(
modifier = Modifier.size(64.dp),
contentAlignment = Alignment.TopEnd
) {
// 底层:头像
Icon(
imageVector = Icons.Default.Person,
contentDescription = "头像",
modifier = Modifier.size(64.dp),
tint = MaterialTheme.colorScheme.primary
)
// 顶层:小红点
Box(
modifier = Modifier
.size(16.dp)
.background(Color.Red, CircleShape)
.border(2.dp, Color.White, CircleShape)
)
}
}
contentAlignment 控制子组件的默认对齐方式。上面代码里 TopEnd 表示子组件默认对齐到右上角。但注意,这个对齐只对「没有指定 Modifier.align」的子组件生效。
3.5 Modifier 的概念与链式调用
好,接下来聊聊 Modifier。这东西是 Compose 里最常用的「工具链」。
你想想看,在传统 View 系统里,你要给一个按钮设置宽高、边距、背景、点击事件,得写好几行代码。在 Compose 里,全通过 Modifier 链式搞定。
@Composable
fun StyledButton() {
Button(
onClick = { /* 点击 */ },
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.height(48.dp)
.background(Color.Blue, RoundedCornerShape(8.dp))
) {
Text("提交")
}
}
看到没?fillMaxWidth、padding、height、background 全部串在一起。这就是链式调用。
每个 Modifier 函数返回一个新的 Modifier 对象,所以可以一直 . 下去。顺序很重要!
Modifier 的常用分类:
| 类别 | 常用函数 | 作用 |
|---|---|---|
| 尺寸 | fillMaxWidth、height、width、size | 控制组件大小 |
| 边距 | padding、margin(通过 offset) | 控制组件间距 |
| 背景 | background、border | 控制组件外观 |
| 事件 | clickable、pointerInput | 控制交互 |
| 布局 | align、weight、aspectRatio | 控制对齐和比例 |
3.6 组合使用:一个完整的例子
最后,我们把这些知识串起来,做一个简单的「商品卡片」布局。
@Composable
fun ProductCard(productName: String, price: String) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 商品图片占位
Box(
modifier = Modifier
.size(80.dp)
.background(Color.LightGray, RoundedCornerShape(8.dp)),
contentAlignment = Alignment.Center
) {
Icon(Icons.Default.Image, contentDescription = "商品图片")
}
// 商品信息
Column(
modifier = Modifier
.weight(1f)
.padding(start = 12.dp)
) {
Text(
text = productName,
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = price,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.primary
)
}
}
}
}
这个例子用了:
- Card 作为外层容器
- Row 水平排列图片和文字
- Box 做图片占位
- Column 垂直排列商品名和价格
- Modifier 链式调用控制尺寸、边距、对齐
嗯,到这里你应该对 Column、Row、Box 和 Modifier 有了比较清晰的认识。说白了,布局就是「选对容器 + 用好 Modifier」。多写几次,手感自然就来了。
- Column 垂直排,Row 水平排,Box 层叠排
- Arrangement 控制排列方式,Alignment 控制对齐方式
- Modifier 是链式调用的工具,顺序影响最终效果
- 先尺寸,再边距,最后背景和点击——记住这个顺序