如何在Jetpack Compose中实现多行芯片组?

17

如何在Jetpack Compose中获得这样的布局?

所以,我已经创建了一个Chip组件,并像这样在LazyRow中使用:

LazyRow(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(16.dp),
    ){
   items.forEach { it ->
            item {
                CustomChip(
                    item = it,
                    isSelected = it == currentItem,
                    onItemChanged = {
                        onItemChanged(it)
                    }
                )
            }
        }
}

但是,我希望实现类似上述图片的布局。即,如果芯片数量达到屏幕末端,则新的芯片应该在新的一行出现。
3个回答

35

更新。现在您可以使用系统FlowRow

val words = LoremIpsum(10).values.first()
    .split(" ", "\n")

FlowRow(
    horizontalArrangement = Arrangement.spacedBy(7.dp),
    verticalArrangement = Arrangement.spacedBy(7.dp),
    modifier = Modifier
        .padding(7.dp)
) {
    words.forEach { word ->
        Text(
            word,
            modifier = Modifier
                .background(color = Color.Gray, shape = CircleShape)
                .padding(vertical = 3.dp, horizontal = 5.dp)
        )
    }
}

如果你有兴趣自己构建类似的东西,你可以使用Layout来实现:
@Composable
fun ChipVerticalGrid(
    modifier: Modifier = Modifier,
    spacing: Dp,
    content: @Composable () -> Unit
) {
    Layout(
        content = content,
        modifier = modifier
    ) { measurables, constraints ->
        var currentRow = 0
        var currentOrigin = IntOffset.Zero
        val spacingValue = spacing.toPx().toInt()
        val placeables = measurables.map { measurable ->
            val placeable = measurable.measure(constraints)

            if (currentOrigin.x > 0f && currentOrigin.x + placeable.width > constraints.maxWidth) {
                currentRow += 1
                currentOrigin = currentOrigin.copy(x = 0, y = currentOrigin.y + placeable.height + spacingValue)
            }

            placeable to currentOrigin.also {
                currentOrigin = it.copy(x = it.x + placeable.width + spacingValue)
            }
        }

        layout(
            width = constraints.maxWidth,
            height = placeables.lastOrNull()?.run { first.height + second.y } ?: 0
        ) {
            placeables.forEach {
                val (placeable, origin) = it
                placeable.place(origin.x, origin.y)
            }
        }
    }
}

使用方法:

val words = LoremIpsum(10).values.first()
    .split(" ", "\n")

ChipVerticalGrid(
    spacing = 7.dp,
    modifier = Modifier
        .padding(7.dp)
) {
    words.forEach { word ->
        Text(
            word,
            modifier = Modifier
                .background(color = Color.Gray, shape = CircleShape)
                .padding(vertical = 3.dp, horizontal = 5.dp)
        )
    }
}

结果:


谢谢这种解决方案。但是两种解决方案都不支持滚动。 - kuzdu
2
好的:这很容易实现。只需将.verticalScroll(scrollState)添加到flowLayout的修饰符(modifier)中即可。 - kuzdu
你的原始回答非常有用且可自定义,谢谢! - Ivette

4

1

[2023] Google 官方:

https://developer.android.com/jetpack/compose/layouts/flow

FlowRow(
    modifier = modifier,
    horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
    items.forEach { it ->
        item {
            CustomChip(
                item = it,
                isSelected = it == currentItem,
                onItemChanged = {
                    onItemChanged(it)
                }
            )
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接