Jetpack Compose:检测子项目溢出并添加更多徽章

Jas*_*son 4 android android-jetpack-compose

目标

我想在可用空间中容纳尽可能多的项目,并在末尾添加“+{num}”徽章以指示是否还有更多项目。像下图这样的东西。

在此输入图像描述

问题

由于事先不知道物品(即本例中的筹码)的数量和大小以及可用空间,因此很难确切地知道可以容纳多少筹码。此外,Compose 仅​​对子项进行一次测量并立即进行布局。

我尝试过的

我尝试了以下方法,但还没有完全实现。

@Composable
fun MainScreen() {
    Column {

        val states = arrayOf(
            "NY", "CA", "NV", "PA", "AZ", "AK", "NE", "CT", "CO", "FL", "IL", "KS", "WA"
        )

        var chipCount by remember { mutableStateOf(0) }

        Row(
            modifier = Modifier
                .padding(horizontal = 16.dp)
                .wrapContentHeight(),
            verticalAlignment = Alignment.CenterVertically
        ) {

            ChipRow(
                modifier = Modifier
                    .padding(end = 4.dp)
                    .weight(1f, fill = false),
                onPlacementComplete = { chipCount = it }
            ) {
                for (state in states) {
                    Chip(
                        modifier = Modifier
                            .padding(4.dp)
                            .wrapContentSize(), text = state
                    )
                }
            }

            Text(text = "+${states.size - chipCount}", style = MaterialTheme.typography.h6)
        }
    }
}

@Composable
fun Chip(
    text: String,
    modifier: Modifier = Modifier
) {
    Surface(
        color = Color.LightGray,
        shape = CircleShape,
        modifier = modifier
    ) {
        Text(
            text = text,
            textAlign = TextAlign.Center,
            style = MaterialTheme.typography.body1,
            modifier = Modifier.padding(6.dp)
        )
    }
}

@Composable
fun ChipRow(
    modifier: Modifier = Modifier,
    onPlacementComplete: (Int) -> Unit,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->

        val placeables = measurables.map { it.measure(constraints) };

        var counter = 0

        layout(constraints.maxWidth, constraints.maxHeight) {
            var xPosition = 0
            for (placeable in placeables) {
                if (xPosition + placeable.width > constraints.maxWidth) break
                placeable.placeRelative(x = xPosition, 0)
                xPosition += placeable.width
                counter++
            }
            onPlacementComplete(counter)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

首先,它看起来很糟糕,而不是一个合法的解决方案。其次,它没有按预期工作。输出如下所示。

在此输入图像描述

要求

我浏览了自定义布局的官方指南并进行了许多谷歌搜索。但又想不出更好的办法。你能帮忙解决这种情况吗?参考链接、指向错误等,任何内容都值得赞赏。

提前致谢!

Phi*_*hov 5

您已经超过了最大约束值 ( layout(constraints.maxWidth, constraints.maxHeight)),这就是您的视图占据整个屏幕的原因。

您需要传递所需的视图大小,例如如下所示:

data class Item(val placeable: Placeable, val xPosition: Int)

val items = mutableListOf<Item>()
var xPosition = 0
for (placeable in placeables) {
    if (xPosition + placeable.width > constraints.maxWidth) break
    items.add(Item(placeable, xPosition))
    xPosition += placeable.width
}

layout(
    width = items.last().let { it.xPosition + it.placeable.width },
    height = items.maxOf { it.placeable.height }
) {
    items.forEach {
        it.placeable.place(it.xPosition, 0)
    }
    onPlacementComplete(items.count())
}
Run Code Online (Sandbox Code Playgroud)

结果: