Compose 流式布局
@Composable fun StaggeredFlow( modifier: Modifier = Modifier, itemSpacing: Dp = 0.dp, lineSpacing: Dp = 0.dp, gravity: Int = Gravity.LEFT, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> var lineWidth = 0 var totalHeight = 0 var lineHeight = 0 var mAllPlaceables = mutableListOf<MutableList<Placeable>>() // 每一行最高的高度 var mLineHeight = mutableListOf<Int>() // 每行放置的内容 var lineViews = mutableListOf<Placeable>() // 不要进一步限制子视图,使用给定的约束来测量它们 val placeables = measurables.mapIndexed { i, measurable -> // 测量每个子视图 val placeable = measurable.measure(constraints) var childWidth = placeable.width var childHeight = placeable.height if(lineWidth + childWidth > constraints.maxWidth){ mLineHeight.add(lineHeight) mAllPlaceables.add(lineViews) lineViews = mutableListOf() lineViews.add(placeable) totalHeight +=lineHeight lineWidth = childWidth lineHeight = childHeight totalHeight += lineSpacing.toPx().toInt() }else{ lineWidth += childWidth + if (i==0) 0 else itemSpacing.toPx().toInt() lineHeight = maxOf(lineHeight,childHeight) lineViews.add(placeable) } if(i == measurables.size - 1){ totalHeight += lineHeight mLineHeight.add(lineHeight) mAllPlaceables.add(lineViews) } } // 设置父布局的大小,摆放子视图 layout(constraints.maxWidth, totalHeight) { var topOffset = 0 var leftOffset = 0 for(i in mAllPlaceables.indices){ lineViews = mAllPlaceables[i] lineHeight = mLineHeight[i] for (j in lineViews.indices){ val child = lineViews[j] val childWidth = child.width val childHeight = child.height val childTop = getItemTop(gravity,lineHeight,topOffset,childHeight) child.placeRelative(leftOffset,childTop) leftOffset += childWidth + lineSpacing.toPx().toInt() } leftOffset = 0 topOffset += lineHeight + lineSpacing.toPx().toInt() } } } } private fun getItemTop(gravity: Int,lineHeight: Int,topOffset: Int,childHeight: Int): Int { return when(gravity){ Gravity.CENTER -> topOffset + (lineHeight-childHeight) / 2 Gravity.BOTTOM -> topOffset + lineHeight-childHeight else -> topOffset } }