Jetpack Compose 中 Row 与 Column 布局
目录
一、概述
Jetpack Compose 提供了两种最基础的线性布局容器:Row 和 Column。
| 布局容器 | 排列方向 | 主轴 | 交叉轴 |
|---|---|---|---|
Row | 水平方向 | 水平 (Horizontal) | 垂直 (Vertical) |
Column | 垂直方向 | 垂直 (Vertical) | 水平 (Horizontal) |
Row 布局示意图:
┌─────────────────────────────────────┐
│ [Item1] [Item2] [Item3] [Item4] │ ← 水平排列
└─────────────────────────────────────┘
Column 布局示意图:
┌─────────┐
│ [Item1] │
├─────────┤
│ [Item2] │
├─────────┤
│ [Item3] │ ← 垂直排列
├─────────┤
│ [Item4] │
└─────────┘
二、Row 布局详解
2.1 基本定义
Row 是一个水平方向的线性布局容器,用于在水平轴上排列其子组件。
@Composable
inline fun Row(
modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
content: @Composable RowScope.() -> Unit
)
参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modifier | Modifier | Modifier | 用于修改布局的修饰符 |
horizontalArrangement | Arrangement.Horizontal | Arrangement.Start | 水平方向排列方式 |
verticalAlignment | Alignment.Vertical | Alignment.Top | 垂直方向对齐方式 |
content | RowScope.() -> Unit | - | 子组件内容 |
2.2 horizontalArrangement 参数详解
horizontalArrangement 用于控制子组件在水平方向上的排列方式。
Arrangement 效果示意图:
Start: [A][B][C]
End: [A][B][C]
Center: [A][B][C]
SpaceBetween: [A] [B] [C]
SpaceAround: [A] [B] [C]
SpaceEvenly: [A] [B] [C]
| 参数值 | 意义 | 适用场景 |
|---|---|---|
Arrangement.Start | 子组件从水平方向的起始位置开始排列(默认值) | 左对齐布局 |
Arrangement.End | 子组件从水平方向的结束位置开始排列 | 右对齐布局 |
Arrangement.Center | 子组件在水平方向上居中排列 | 居中对齐 |
Arrangement.SpaceBetween | 子组件之间均匀分布,首尾子组件分别位于起始和结束位置 | 两端对齐 |
Arrangement.SpaceAround | 子组件之间均匀分布,首尾子组件与容器边缘有一半的间距 | 均匀分布带边距 |
Arrangement.SpaceEvenly | 子组件之间及与容器边缘的间距均相等 | 完全均匀分布 |
Arrangement.spacedBy(dp, alignment) | 自定义子组件之间的固定间距 | 固定间距布局 |
代码示例:
@Composable
fun RowArrangementDemo() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Start
ArrangementRow(
title = "Arrangement.Start",
arrangement = Arrangement.Start
)
// Center
ArrangementRow(
title = "Arrangement.Center",
arrangement = Arrangement.Center
)
// End
ArrangementRow(
title = "Arrangement.End",
arrangement = Arrangement.End
)
// SpaceBetween
ArrangementRow(
title = "Arrangement.SpaceBetween",
arrangement = Arrangement.SpaceBetween
)
// SpaceAround
ArrangementRow(
title = "Arrangement.SpaceAround",
arrangement = Arrangement.SpaceAround
)
// SpaceEvenly
ArrangementRow(
title = "Arrangement.SpaceEvenly",
arrangement = Arrangement.SpaceEvenly
)
// spacedBy
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.LightGray)
.padding(8.dp),
horizontalArrangement = Arrangement.spacedBy(24.dp)
) {
DemoBox(text = "A")
DemoBox(text = "B")
DemoBox(text = "C")
}
Text("Arrangement.spacedBy(24.dp)", fontSize = 12.sp, color = Color.Gray)
}
}
@Composable
private fun ArrangementRow(
title: String,
arrangement: Arrangement.Horizontal
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.LightGray)
.padding(8.dp),
horizontalArrangement = arrangement
) {
DemoBox(text = "A")
DemoBox(text = "B")
DemoBox(text = "C")
}
Text(title, fontSize = 12.sp, color = Color.Gray)
}
}
@Composable
private fun DemoBox(text: String) {
Box(
modifier = Modifier
.size(40.dp)
.background(Color(0xFF6200EE)),
contentAlignment = Alignment.Center
) {
Text(text, color = Color.White, fontWeight = FontWeight.Bold)
}
}
2.3 verticalAlignment 参数详解
verticalAlignment 用于控制子组件在垂直方向上的对齐方式。
VerticalAlignment 效果示意图:
Top: ┌───┐ ┌───┐ ┌───┐
│ A │ │ B │ │ C │
└───┘ └───┘ └───┘
Center: ┌───┐ ┌───┐ ┌───┐
│ A │ │ B │ │ C │
└───┘ └───┘ └───┘
Bottom: ┌───┐ ┌───┐ ┌───┐
│ A │ │ B │ │ C │
└───┘ └───┘ └───┘
| 参数值 | 意义 | 适用场景 |
|---|---|---|
Alignment.Top | 子组件与垂直方向的顶部对齐(默认值) | 顶部对齐 |
Alignment.CenterVertically | 子组件在垂直方向上居中对齐 | 垂直居中 |
Alignment.Bottom | 子组件与垂直方向的底部对齐 | 底部对齐 |
代码示例:
@Composable
fun RowAlignmentDemo() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Top
AlignmentRow(
title = "Alignment.Top",
alignment = Alignment.Top
)
// CenterVertically
AlignmentRow(
title = "Alignment.CenterVertically",
alignment = Alignment.CenterVertically
)
// Bottom
AlignmentRow(
title = "Alignment.Bottom",
alignment = Alignment.Bottom
)
}
}
@Composable
private fun AlignmentRow(
title: String,
alignment: Alignment.Vertical
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.height(80.dp)
.background(Color.LightGray)
.padding(8.dp),
verticalAlignment = alignment,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Box(
modifier = Modifier
.size(30.dp)
.background(Color.Red)
)
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Green)
)
Box(
modifier = Modifier
.size(40.dp)
.background(Color.Blue)
)
}
Text(title, fontSize = 12.sp, color = Color.Gray)
}
}
2.4 Row 综合使用示例
@Composable
fun RowCompleteExample() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
// 示例1:工具栏布局
ToolbarExample()
// 示例2:卡片信息行
CardInfoRow()
// 示例3:标签组
TagGroupExample()
}
}
@Composable
private fun ToolbarExample() {
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.background(Color(0xFF6200EE))
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// 左侧:返回按钮
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "Back",
tint = Color.White
)
// 中间:标题
Text(
text = "页面标题",
color = Color.White,
fontSize = 20.sp,
fontWeight = FontWeight.Medium
)
// 右侧:菜单按钮
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "Menu",
tint = Color.White
)
}
}
@Composable
private fun CardInfoRow() {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White, RoundedCornerShape(8.dp))
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// 左侧信息
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(48.dp)
.background(Color(0xFFE3F2FD), CircleShape),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Person,
contentDescription = null,
tint = Color(0xFF1976D2)
)
}
Column {
Text(
text = "用户名",
fontWeight = FontWeight.Bold,
fontSize = 16.sp
)
Text(
text = "user@example.com",
fontSize = 14.sp,
color = Color.Gray
)
}
}
// 右侧箭头
Icon(
imageVector = Icons.Default.ChevronRight,
contentDescription = null,
tint = Color.Gray
)
}
}
@Composable
private fun TagGroupExample() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
val tags = listOf("Android", "Kotlin", "Compose", "Jetpack")
tags.forEach { tag ->
Box(
modifier = Modifier
.background(Color(0xFFF5F5F5), RoundedCornerShape(16.dp))
.padding(horizontal = 12.dp, vertical = 6.dp)
) {
Text(
text = tag,
fontSize = 14.sp,
color = Color.DarkGray
)
}
}
}
}
三、Column 布局详解
3.1 基本定义
Column 是一个垂直方向的线性布局容器,用于在垂直轴上排列其子组件。
@Composable
inline fun Column(
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
content: @Composable ColumnScope.() -> Unit
)
参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modifier | Modifier | Modifier | 用于修改布局的修饰符 |
verticalArrangement | Arrangement.Vertical | Arrangement.Top | 垂直方向排列方式 |
horizontalAlignment | Alignment.Horizontal | Alignment.Start | 水平方向对齐方式 |
content | ColumnScope.() -> Unit | - | 子组件内容 |
3.2 verticalArrangement 参数详解
verticalArrangement 用于控制子组件在垂直方向上的排列方式。
| 参数值 | 意义 | 适用场景 |
|---|---|---|
Arrangement.Top | 子组件从垂直方向的起始位置开始排列(默认值) | 顶部对齐布局 |
Arrangement.Bottom | 子组件从垂直方向的结束位置开始排列 | 底部对齐布局 |
Arrangement.Center | 子组件在垂直方向上居中排列 | 垂直居中布局 |
Arrangement.SpaceBetween | 子组件之间均匀分布,首尾子组件分别位于起始和结束位置 | 垂直两端对齐 |
Arrangement.SpaceAround | 子组件之间均匀分布,首尾子组件与容器边缘有一半的间距 | 均匀分布带边距 |
Arrangement.SpaceEvenly | 子组件之间及与容器边缘的间距均相等 | 完全均匀分布 |
Arrangement.spacedBy(dp, alignment) | 自定义子组件之间的固定间距 | 固定间距布局 |
代码示例:
@Composable
fun ColumnArrangementDemo() {
Row(
modifier = Modifier.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
// Top
ArrangementColumn(
title = "Top",
arrangement = Arrangement.Top
)
// Center
ArrangementColumn(
title = "Center",
arrangement = Arrangement.Center
)
// Bottom
ArrangementColumn(
title = "Bottom",
arrangement = Arrangement.Bottom
)
// SpaceBetween
ArrangementColumn(
title = "SpaceBetween",
arrangement = Arrangement.SpaceBetween
)
}
}
@Composable
private fun ArrangementColumn(
title: String,
arrangement: Arrangement.Vertical
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier
.width(80.dp)
.height(200.dp)
.background(Color.LightGray)
.padding(8.dp),
verticalArrangement = arrangement,
horizontalAlignment = Alignment.CenterHorizontally
) {
DemoBox(text = "1")
DemoBox(text = "2")
DemoBox(text = "3")
}
Text(title, fontSize = 10.sp, color = Color.Gray)
}
}
3.3 horizontalAlignment 参数详解
horizontalAlignment 用于控制子组件在水平方向上的对齐方式。
| 参数值 | 意义 | 适用场景 |
|---|---|---|
Alignment.Start | 子组件与水平方向的起始位置对齐(默认值) | 左对齐 |
Alignment.CenterHorizontally | 子组件在水平方向上居中对齐 | 水平居中 |
Alignment.End | 子组件与水平方向的结束位置对齐 | 右对齐 |
代码示例:
@Composable
fun ColumnAlignmentDemo() {
Row(
modifier = Modifier.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
// Start
AlignmentColumn(
title = "Start",
alignment = Alignment.Start
)
// CenterHorizontally
AlignmentColumn(
title = "Center",
alignment = Alignment.CenterHorizontally
)
// End
AlignmentColumn(
title = "End",
alignment = Alignment.End
)
}
}
@Composable
private fun AlignmentColumn(
title: String,
alignment: Alignment.Horizontal
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier
.width(120.dp)
.background(Color.LightGray)
.padding(8.dp),
horizontalAlignment = alignment
) {
Box(
modifier = Modifier
.width(80.dp)
.height(30.dp)
.background(Color.Red)
)
Spacer(modifier = Modifier.height(8.dp))
Box(
modifier = Modifier
.width(50.dp)
.height(30.dp)
.background(Color.Green)
)
Spacer(modifier = Modifier.height(8.dp))
Box(
modifier = Modifier
.width(100.dp)
.height(30.dp)
.background(Color.Blue)
)
}
Text(title, fontSize = 10.sp, color = Color.Gray)
}
}
3.4 Column 综合使用示例
@Composable
fun ColumnCompleteExample() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
// 示例1:表单布局
FormExample()
// 示例2:卡片详情
CardDetailExample()
// 示例3:底部操作栏
BottomActionExample()
}
}
@Composable
private fun FormExample() {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = "登录",
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
// 用户名输入
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "用户名",
fontSize = 14.sp,
color = Color.Gray
)
OutlinedTextField(
value = "",
onValueChange = {},
modifier = Modifier.fillMaxWidth(),
placeholder = { Text("请输入用户名") }
)
}
// 密码输入
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "密码",
fontSize = 14.sp,
color = Color.Gray
)
OutlinedTextField(
value = "",
onValueChange = {},
modifier = Modifier.fillMaxWidth(),
placeholder = { Text("请输入密码") },
visualTransformation = PasswordVisualTransformation()
)
}
// 登录按钮
Button(
onClick = {},
modifier = Modifier.fillMaxWidth()
) {
Text("登录")
}
}
}
@Composable
private fun CardDetailExample() {
Column(
modifier = Modifier
.fillMaxWidth()
.background(Color.White, RoundedCornerShape(12.dp))
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 标题行
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "订单详情",
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
Text(
text = "已完成",
fontSize = 14.sp,
color = Color(0xFF4CAF50)
)
}
Divider()
// 信息列表
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
InfoRow(label = "订单号", value = "ORD20240115001")
InfoRow(label = "下单时间", value = "2024-01-15 14:30")
InfoRow(label = "支付方式", value = "微信支付")
InfoRow(label = "配送地址", value = "北京市朝阳区xxx街道")
}
Divider()
// 金额
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("实付金额", color = Color.Gray)
Text(
"¥299.00",
fontWeight = FontWeight.Bold,
color = Color(0xFFFF5722)
)
}
}
}
@Composable
private fun InfoRow(label: String, value: String) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(label, color = Color.Gray, fontSize = 14.sp)
Text(value, fontSize = 14.sp)
}
}
@Composable
private fun BottomActionExample() {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Button(
onClick = {},
modifier = Modifier.fillMaxWidth()
) {
Text("确认提交")
}
TextButton(onClick = {}) {
Text("取消")
}
}
}
四、参数配置与组合使用
4.1 多参数组合配置
@Composable
fun CombinedParametersExample() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
// Row组合示例
Row(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color(0xFFE3F2FD)),
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically
) {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
// Column组合示例
Column(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(Color(0xFFF3E5F5)),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Item A")
Text("Item B")
Text("Item C")
}
}
}
4.2 嵌套布局
@Composable
fun NestedLayoutExample() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
// 顶部导航栏
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = {}) {
Icon(Icons.Default.Menu, null)
}
Text("首页", fontWeight = FontWeight.Bold)
IconButton(onClick = {}) {
Icon(Icons.Default.Search, null)
}
}
// 中间内容区
Column(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 横向滚动内容
Row(
modifier = Modifier.horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
repeat(5) { index ->
Card(
modifier = Modifier.size(120.dp),
colors = CardDefaults.cardColors(
containerColor = Color(0xFFBBDEFB)
)
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Card $index")
}
}
}
}
// 列表项
repeat(3) { index ->
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = Color(0xFFE8F5E9)
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
"列表项 ${index + 1}",
fontWeight = FontWeight.Medium
)
Text(
"描述信息",
fontSize = 12.sp,
color = Color.Gray
)
}
Icon(Icons.Default.ChevronRight, null)
}
}
}
}
// 底部导航栏
Row(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
val items = listOf("首页", "分类", "购物车", "我的")
items.forEach { item ->
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(Icons.Default.Home, null)
Text(item, fontSize = 12.sp)
}
}
}
}
}
4.3 与 Modifier 的配合使用
@Composable
fun ModifierCombinationExample() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 使用 weight 分配空间
Row(
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color.Red)
)
Box(
modifier = Modifier
.weight(2f)
.height(50.dp)
.background(Color.Green)
)
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color.Blue)
)
}
// 使用 padding 和 border
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.border(1.dp, Color.Gray, RoundedCornerShape(8.dp))
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("左侧内容")
Text("右侧内容")
}
// 使用 size 和 aspectRatio
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
Box(
modifier = Modifier
.size(80.dp)
.background(Color(0xFFFFCDD2), CircleShape)
)
Box(
modifier = Modifier
.size(80.dp)
.aspectRatio(1f)
.background(Color(0xFFC8E6C9), RoundedCornerShape(16.dp))
)
Box(
modifier = Modifier
.width(80.dp)
.height(60.dp)
.background(Color(0xFFBBDEFB))
)
}
}
}
五、RowScope 与 ColumnScope
5.1 Scope 作用域说明
RowScope 和 ColumnScope 提供了在特定布局中使用的专用修饰符。
5.2 RowScope 专属修饰符
@Composable
fun RowScopeDemo() {
Row(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.padding(16.dp)
) {
// weight - 按比例分配剩余空间
Box(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.background(Color.Red)
)
Box(
modifier = Modifier
.weight(2f)
.fillMaxHeight()
.background(Color.Green)
)
Box(
modifier = Modifier
.weight(1f)
.fillMaxHeight()
.background(Color.Blue)
)
}
}
RowScope 可用修饰符:
| 修饰符 | 作用 |
|---|---|
Modifier.weight(weight, fill) | 按比例分配剩余水平空间 |
Modifier.align(alignment) | 单独设置垂直方向对齐方式 |
5.3 ColumnScope 专属修饰符
@Composable
fun ColumnScopeDemo() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
// 固定高度头部
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.background(Color(0xFF6200EE))
)
// weight 分配剩余空间给内容区
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.background(Color(0xFFE3F2FD))
) {
Text(
"内容区域(自适应高度)",
modifier = Modifier.align(Alignment.Center)
)
}
// 固定高度底部
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.background(Color(0xFF4CAF50))
)
}
}
ColumnScope 可用修饰符:
| 修饰符 | 作用 |
|---|---|
Modifier.weight(weight, fill) | 按比例分配剩余垂直空间 |
Modifier.align(alignment) | 单独设置水平方向对齐方式 |
Modifier.alignBy(alignmentLine) | 基于对齐线对齐 |
5.4 子组件独立对齐
@Composable
fun IndividualAlignmentExample() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// Row 中子组件独立对齐
Row(
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.background(Color.LightGray),
verticalAlignment = Alignment.CenterVertically
) {
Text(
"顶部对齐",
modifier = Modifier.align(Alignment.Top)
)
Spacer(modifier = Modifier.width(16.dp))
Text(
"居中对齐(默认)"
)
Spacer(modifier = Modifier.width(16.dp))
Text(
"底部对齐",
modifier = Modifier.align(Alignment.Bottom)
)
}
// Column 中子组件独立对齐
Column(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.LightGray),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
"左对齐",
modifier = Modifier.align(Alignment.Start)
)
Text(
"居中对齐(默认)"
)
Text(
"右对齐",
modifier = Modifier.align(Alignment.End)
)
}
}
}
六、常见问题与最佳实践
6.1 布局溢出问题
@Composable
fun OverflowSolutionExample() {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 问题:Row内容超出屏幕宽度
Text("问题:内容溢出", fontWeight = FontWeight.Bold)
Row {
repeat(10) {
Box(
modifier = Modifier
.size(60.dp)
.background(Color.Red)
)
}
}
// 解决方案1:添加水平滚动
Text("方案1:horizontalScroll", fontWeight = FontWeight.Bold)
Row(
modifier = Modifier.horizontalScroll(rememberScrollState())
) {
repeat(10) {
Box(
modifier = Modifier
.size(60.dp)
.background(Color.Green)
)
}
}
// 解决方案2:使用 weight 分配空间
Text("方案2:weight 分配", fontWeight = FontWeight.Bold)
Row(
modifier = Modifier.fillMaxWidth()
) {
repeat(5) {
Box(
modifier = Modifier
.weight(1f)
.height(60.dp)
.background(Color.Blue)
)
}
}
}
}
6.2 权重分配技巧
@Composable
fun WeightDistributionExample() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
// 示例1:头部固定,内容自适应,底部固定
Row(
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier
.width(80.dp)
.height(50.dp)
.background(Color.Gray),
contentAlignment = Alignment.Center
) {
Text("固定", color = Color.White)
}
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color(0xFF6200EE)),
contentAlignment = Alignment.Center
) {
Text("自适应", color = Color.White)
}
Box(
modifier = Modifier
.width(80.dp)
.height(50.dp)
.background(Color.Gray),
contentAlignment = Alignment.Center
) {
Text("固定", color = Color.White)
}
}
Spacer(modifier = Modifier.height(16.dp))
// 示例2:按比例分配
Row(
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier
.weight(1f)
.height(50.dp)
.background(Color.Red),
contentAlignment = Alignment.Center
) {
Text("1份", color = Color.White)
}
Box(
modifier = Modifier
.weight(2f)
.height(50.dp)
.background(Color.Green),
contentAlignment = Alignment.Center
) {
Text("2份", color = Color.White)
}
Box(
modifier = Modifier
.weight(3f)
.height(50.dp)
.background(Color.Blue),
contentAlignment = Alignment.Center
) {
Text("3份", color = Color.White)
}
}
}
}
6.3 性能优化建议
/**
* Row/Column 性能优化最佳实践
*/
object LayoutPerformanceTips {
/**
* 1. 避免过深嵌套
* 尽量保持布局层级扁平
*/
@Composable
fun FlatLayout() {
// ✅ 推荐:扁平结构
Row {
// 直接放置子组件
}
// ❌ 避免:过深嵌套
Row {
Column {
Row {
Column {
// 深层嵌套影响性能
}
}
}
}
}
/**
* 2. 大量数据使用 Lazy 系列
*/
@Composable
fun LargeDataList() {
// ✅ 推荐:LazyRow/LazyColumn
LazyColumn {
items(1000) { index ->
ListItem(index)
}
}
// ❌ 避免:直接使用 Column
Column {
repeat(1000) { index ->
ListItem(index)
}
}
}
/**
* 3. 合理使用 remember 缓存计算
*/
@Composable
fun CachedLayout() {
val arrangement = remember {
Arrangement.spacedBy(16.dp)
}
Column(
verticalArrangement = arrangement
) {
// 子组件
}
}
}
6.4 响应式布局
@Composable
fun ResponsiveLayoutExample() {
// 使用 BoxWithConstraints 获取容器尺寸
BoxWithConstraints(
modifier = Modifier.fillMaxSize()
) {
val isWideScreen = maxWidth > 600.dp
if (isWideScreen) {
// 宽屏:水平排列
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
SidePanel(modifier = Modifier.weight(1f))
MainContent(modifier = Modifier.weight(2f))
}
} else {
// 窄屏:垂直排列
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
SidePanel(modifier = Modifier.height(200.dp))
MainContent(modifier = Modifier.weight(1f))
}
}
}
}
@Composable
private fun SidePanel(modifier: Modifier = Modifier) {
Box(
modifier = modifier.background(Color(0xFFE3F2FD)),
contentAlignment = Alignment.Center
) {
Text("侧边栏")
}
}
@Composable
private fun MainContent(modifier: Modifier = Modifier) {
Box(
modifier = modifier.background(Color(0xFFF3E5F5)),
contentAlignment = Alignment.Center
) {
Text("主内容区")
}
}
七、完整代码示例
7.1 完整页面布局示例
@Composable
fun CompletePageExample() {
Column(
modifier = Modifier.fillMaxSize()
) {
// 顶部应用栏
TopAppBar()
// 可滚动内容区
Column(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.verticalScroll(rememberScrollState())
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 用户信息卡片
UserProfileCard()
// 统计数据行
StatisticsRow()
// 功能菜单网格
FeatureMenuGrid()
// 最近活动列表
RecentActivityList()
}
// 底部导航栏
BottomNavigationBar()
}
}
@Composable
private fun TopAppBar() {
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.background(Color(0xFF6200EE))
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.Menu,
contentDescription = "Menu",
tint = Color.White
)
Text(
text = "我的应用",
color = Color.White,
fontSize = 20.sp,
fontWeight = FontWeight.Medium
)
Icon(
imageVector = Icons.Default.Notifications,
contentDescription = "Notifications",
tint = Color.White
)
}
}
@Composable
private fun UserProfileCard() {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White, RoundedCornerShape(12.dp))
.padding(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
// 头像
Box(
modifier = Modifier
.size(64.dp)
.background(Color(0xFFBBDEFB), CircleShape),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Person,
contentDescription = null,
modifier = Modifier.size(32.dp),
tint = Color(0xFF1976D2)
)
}
// 用户信息
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = "张三",
fontSize = 20.sp,
fontWeight = FontWeight.Bold
)
Text(
text = "高级会员",
fontSize = 14.sp,
color = Color(0xFFFF9800)
)
Text(
text = "zhangsan@example.com",
fontSize = 12.sp,
color = Color.Gray
)
}
// 编辑按钮
Icon(
imageVector = Icons.Default.Edit,
contentDescription = "Edit",
tint = Color.Gray
)
}
}
@Composable
private fun StatisticsRow() {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
StatisticItem(
title = "订单",
value = "128",
modifier = Modifier.weight(1f)
)
StatisticItem(
title = "收藏",
value = "56",
modifier = Modifier.weight(1f)
)
StatisticItem(
title = "优惠券",
value = "12",
modifier = Modifier.weight(1f)
)
StatisticItem(
title = "积分",
value = "3,580",
modifier = Modifier.weight(1f)
)
}
}
@Composable
private fun StatisticItem(
title: String,
value: String,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.background(Color.White, RoundedCornerShape(8.dp))
.padding(12.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = value,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = Color(0xFF6200EE)
)
Text(
text = title,
fontSize = 12.sp,
color = Color.Gray
)
}
}
@Composable
private fun FeatureMenuGrid() {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
FeatureItem(
icon = Icons.Default.ShoppingCart,
title = "购物车",
modifier = Modifier.weight(1f)
)
FeatureItem(
icon = Icons.Default.Favorite,
title = "收藏夹",
modifier = Modifier.weight(1f)
)
FeatureItem(
icon = Icons.Default.LocationOn,
title = "地址管理",
modifier = Modifier.weight(1f)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
FeatureItem(
icon = Icons.Default.History,
title = "浏览记录",
modifier = Modifier.weight(1f)
)
FeatureItem(
icon = Icons.Default.Settings,
title = "设置",
modifier = Modifier.weight(1f)
)
FeatureItem(
icon = Icons.Default.Help,
title = "帮助中心",
modifier = Modifier.weight(1f)
)
}
}
}
@Composable
private fun FeatureItem(
icon: ImageVector,
title: String,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.background(Color.White, RoundedCornerShape(8.dp))
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
imageVector = icon,
contentDescription = title,
tint = Color(0xFF6200EE)
)
Text(
text = title,
fontSize = 12.sp
)
}
}
@Composable
private fun RecentActivityList() {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "最近活动",
fontSize = 16.sp,
fontWeight = FontWeight.Bold
)
repeat(3) { index ->
ActivityItem(
title = "活动 ${index + 1}",
time = "2024-01-${15 + index} 14:30",
description = "完成了订单 #100${index}"
)
}
}
}
@Composable
private fun ActivityItem(
title: String,
time: String,
description: String
) {
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.White, RoundedCornerShape(8.dp))
.padding(12.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(40.dp)
.background(Color(0xFFE3F2FD), CircleShape),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.CheckCircle,
contentDescription = null,
tint = Color(0xFF4CAF50)
)
}
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
Text(
text = title,
fontWeight = FontWeight.Medium
)
Text(
text = description,
fontSize = 12.sp,
color = Color.Gray
)
}
Text(
text = time,
fontSize = 11.sp,
color = Color.LightGray
)
}
}
@Composable
private fun BottomNavigationBar() {
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.background(Color.White)
.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
val items = listOf(
"首页" to Icons.Default.Home,
"分类" to Icons.Default.Category,
"购物车" to Icons.Default.ShoppingCart,
"我的" to Icons.Default.Person
)
items.forEach { (title, icon) ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
Icon(icon, contentDescription = title)
Text(title, fontSize = 11.sp)
}
}
}
}
总结
Row 和 Column 是 Jetpack Compose 中最基础也是最常用的布局容器:
| 特性 | Row | Column |
|---|---|---|
| 排列方向 | 水平 | 垂直 |
| 主轴参数 | horizontalArrangement | verticalArrangement |
| 交叉轴参数 | verticalAlignment | horizontalAlignment |
| Scope修饰符 | weight(), align() | weight(), align() |
核心要点:
-
Arrangement 控制主轴上的排列方式(Start、End、Center、SpaceBetween、SpaceAround、SpaceEvenly、spacedBy)
-
Alignment 控制交叉轴上的对齐方式(Start/Center/End 或 Top/Center/Bottom)
-
Scope修饰符 可以在子组件级别覆盖容器的对齐设置
-
Modifier.weight() 用于按比例分配剩余空间
-
性能优化:避免过深嵌套,大量数据使用Lazy系列,合理使用remember缓存
掌握这些基础布局容器的使用方法,是构建复杂 Compose 界面的基础。