Compose 中的流式布局
FlowRow 和 FlowColumn 是类似于 Row 和 Column 的可组合项,但不同之处在于,当容器空间不足时,项目会流入下一行(或列)。这会创建多行或多列布局,非常适合构建自适应界面。
基本用法
@Composable
private fun FlowRowSimpleUsageExample() {
FlowRow(
modifier = Modifier.padding(8.dp)
) {
ChipItem("Price: High to Low")
ChipItem("Avg rating: 4+")
ChipItem("Free breakfast")
ChipItem("Free cancellation")
ChipItem("£50 pn")
}
}
流式布局的特性
主轴排列
主轴是布置内容的轴(在 FlowRow 中是水平轴)。使用 horizontalArrangement 参数控制项目间的空间分配:
FlowRow(
horizontalArrangement = Arrangement.SpaceBetween // 或其他排列方式
) { /* items */ }
FlowRow 的主轴排列选项包括:
Arrangement.Start(默认值)Arrangement.SpaceBetweenArrangement.CenterArrangement.EndArrangement.SpaceAroundArrangement.spacedBy(8.dp)
对于 FlowColumn,使用 verticalArrangement 获得类似选项。
交叉轴排列
交叉轴是与主轴方向相反的轴。在 FlowRow 中是垂直轴,使用 verticalArrangement 控制:
FlowRow(
verticalArrangement = Arrangement.Center // 垂直居中排列各行
) { /* items */ }
FlowRow 的交叉轴排列选项包括:
Arrangement.Top(默认值)Arrangement.BottomArrangement.Center
对于 FlowColumn,使用 horizontalArrangement 获得类似选项。
单个项目对齐
可以使用 Modifier.align() 为行内各个项目设置不同的对齐方式:
FlowRow {
Box(Modifier.align(Alignment.Bottom).size(50.dp, 80.dp))
Box(Modifier.align(Alignment.CenterVertically).size(50.dp, 60.dp))
Box(Modifier.align(Alignment.Top).size(50.dp, 40.dp))
}
FlowRow 中的对齐选项包括:
Alignment.Top(默认值)Alignment.BottomAlignment.CenterVertically
行/列中的项目数量上限
maxItemsInEachRow 或 maxItemsInEachColumn 参数限制一行/列中的最大项目数:
FlowRow(
maxItemsInEachRow = 3 // 每行最多3个项目
) { /* items */ }
项目权重
Modifier.weight 根据项目所在行/列中的可用空间分配宽度。与 Row 不同,FlowRow 中的权重只考虑当前行中的项目:
FlowRow(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
maxItemsInEachRow = 3
) {
val itemModifier = Modifier
.padding(4.dp)
.height(80.dp)
.weight(1f)
repeat(9) {
Spacer(modifier = itemModifier.background(Color.Blue))
}
}
创建网格布局
结合 maxItemsInEachRow 和 weight 可以创建自适应网格:
val rows = 3
val columns = 3
FlowRow(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
maxItemsInEachRow = rows
) {
val itemModifier = Modifier
.padding(4.dp)
.height(80.dp)
.weight(1f)
.clip(RoundedCornerShape(8.dp))
.background(Color.Blue200)
repeat(rows * columns) {
Spacer(modifier = itemModifier)
}
}
交替网格大小
创建不同大小的项目网格:
FlowRow(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
maxItemsInEachRow = 2
) {
val itemModifier = Modifier
.padding(4.dp)
.height(80.dp)
.clip(RoundedCornerShape(8.dp))
.background(Color.Blue)
repeat(6) { item ->
if ((item + 1) % 3 == 0) {
Spacer(modifier = itemModifier.fillMaxWidth())
} else {
Spacer(modifier = itemModifier.weight(0.5f))
}
}
}
分数大小调整
Modifier.fillMaxWidth(fraction) 指定项目应占用的容器大小比例,与在 Row 中的行为不同:
FlowRow(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
maxItemsInEachRow = 3
) {
val itemModifier = Modifier.clip(RoundedCornerShape(8.dp))
Box(modifier = itemModifier.height(200.dp).width(60.dp).background(Color.Red))
Box(modifier = itemModifier.height(200.dp).fillMaxWidth(0.7f).background(Color.Blue))
Box(modifier = itemModifier.height(200.dp).weight(1f).background(Color.Magenta))
}
fillMaxColumnWidth() 和 fillMaxRowHeight()
确保同一列/行中的项目具有相同宽度/高度:
FlowColumn(
Modifier.padding(20.dp).fillMaxHeight().fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
maxItemsInEachColumn = 5,
) {
repeat(listDesserts.size) {
Box(
Modifier.fillMaxColumnWidth()
.border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp))
.padding(8.dp)
) {
Text(text = listDesserts[it], fontSize = 18.sp, modifier = Modifier.padding(3.dp))
}
}
}
使用流式布局可以轻松创建自适应界面,特别适合处理动态内容或不同屏幕尺寸的场景。