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
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值