列表中的任何想法在 Jetpack compose 中的项目上具有适合/包裹宽度

Ash*_*tel 8 android android-jetpack-compose

我需要实现下一个 UI 元素:

在此处输入图片说明

  • 未知大小的字符串列表
  • 任何项目都应该是包装内容。
  • 如果某个项目不适合该行,他将在下一行。
  • 所有列表/网格都居中

Mac*_*ęga 14

您可以使用它FlowRow来实现这一点。它水平呈现其子项(如Row),但如果它们不适合现有行,也会通过移动到新行来包装它们。

要很好地处理很长的字符串(它们本身不适合单行),您可以设置overflow = TextOverflow.EllipsismaxLines = 1on Text

@Composable
fun HashTagList(hashTags: List<String>) {
    Box(modifier = Modifier.padding(8.dp)) {
        FlowRow(
            mainAxisAlignment = MainAxisAlignment.Center,
            mainAxisSize = SizeMode.Expand,
            crossAxisSpacing = 12.dp,
            mainAxisSpacing = 8.dp
        ) {
            hashTags.forEach { hashTag ->
                Text(
                    text = hashTag,
                    modifier = Modifier.drawBackground(
                        color = colorForHashTag(hashTag),
                        shape = RoundedCornerShape(4.dp)
                    ).padding(8.dp),
                    overflow = TextOverflow.Ellipsis,
                    maxLines = 1
                )
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • FlowRow 和 FlowColumn 现已弃用,您应该使用自定义布局,请参阅此处 https://android-review.googlesource.com/c/platform/frameworks/support/+/1521704 (2认同)

Val*_*kov 12

更新:对于准备使用的解决方案来看看Jetpack的撰写流程布局伴奏库。有关自定义解决方案,请参阅下面的答案。


由于 Compose 版本1.0.0-alpha10 FlowRow 和 FlowColumn 已弃用。我希望将来会有一些内置解决方案,但现在您可以使用弃用说明建议的自定义布局。下面是一个例子:

@Composable
fun TagRow(tags: Collection<String>) {
    SimpleFlowRow(
        verticalGap = 8.dp,
        horizontalGap = 8.dp,
        alignment = Alignment.CenterHorizontally,
        modifier = Modifier.padding(16.dp)
    ) {
        for (tag in tags) {
            Text(
                text = "#$tag",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier
                    .background(Color.LightGray, RoundedCornerShape(4.dp))
                    .padding(4.dp)
            )
        }
    }
}

@Composable
fun SimpleFlowRow(
    modifier: Modifier = Modifier,
    alignment: Alignment.Horizontal = Alignment.Start,
    verticalGap: Dp = 0.dp,
    horizontalGap: Dp = 0.dp,
    content: @Composable () -> Unit
) = Layout(content, modifier) { measurables, constraints ->
    val hGapPx = horizontalGap.roundToPx()
    val vGapPx = verticalGap.roundToPx()

    val rows = mutableListOf<MeasuredRow>()
    val itemConstraints = constraints.copy(minWidth = 0)

    for (measurable in measurables) {
        val lastRow = rows.lastOrNull()
        val placeable = measurable.measure(itemConstraints)

        if (lastRow != null && lastRow.width + hGapPx + placeable.width <= constraints.maxWidth) {
            lastRow.items.add(placeable)
            lastRow.width += hGapPx + placeable.width
            lastRow.height = max(lastRow.height, placeable.height)
        } else {
            val nextRow = MeasuredRow(
                items = mutableListOf(placeable),
                width = placeable.width,
                height = placeable.height
            )

            rows.add(nextRow)
        }
    }

    val width = rows.maxOfOrNull { row -> row.width } ?: 0
    val height = rows.sumBy { row -> row.height } + max(vGapPx.times(rows.size - 1), 0)

    val coercedWidth = width.coerceIn(constraints.minWidth, constraints.maxWidth)
    val coercedHeight = height.coerceIn(constraints.minHeight, constraints.maxHeight)

    layout(coercedWidth, coercedHeight) {
        var y = 0

        for (row in rows) {
            var x = when(alignment) {
                Alignment.Start -> 0
                Alignment.CenterHorizontally -> (coercedWidth - row.width) / 2
                Alignment.End -> coercedWidth - row.width

                else -> throw Exception("unsupported alignment")
            }

            for (item in row.items) {
                item.place(x, y)
                x += item.width + hGapPx
            }

            y += row.height + vGapPx
        }
    }
}

private data class MeasuredRow(
    val items: MutableList<Placeable>,
    var width: Int,
    var height: Int
)
Run Code Online (Sandbox Code Playgroud)

结果: 在此处输入图片说明

您可以在 GitHub 上找到完整的示例代码。

  • 这看起来很棒,但我注意到所有项目都是同时加载的。如果您有超过 1000 个带有图像的项目,这可能会成为一个问题。有没有办法延迟加载项目? (2认同)

Mat*_*sky 5

伴奏中的流程布局正是您所寻找的

您可以在这里找到文档: https: //google.github.io/accompanist/flowlayout/

具体来说,这FlowRow将允许您在示例中实现您想要的目标