首页 > 解决方案 > Jetpack Compose 动态垫片高度

问题描述

我正在使用 Jetpack Compose 1.0.2 版(截至今天的最新稳定版)。

我有一个Columnof multiple LazyRows,其中有一个Image和两个Text

图片

见下面的结构(简化)

val topicList: List<Topics>


Column {
    topicList.forEach { topic ->

        val showList: List<Show> = topic.shows

        Column {
            Text(text = topic.title)

            LazyRow {
                items(showList) { show ->
                    Column {
                        Image()
                        Text(text = show.title)
                        Text(text = show.info)
                    }
                }
            }

            Spacer(Modifier.height(32.dp))
        }
    }
}

问题是Text可组合的show.title并且show.info可以是多行,并且由于每个项目都是延迟加载的,因此在显示在屏幕上之前不会计算高度。结果,下一行的y位置跳来跳去。

要了解发生了什么,请观看此视频:视频链接

如何动态计算Spacer's 的高度以使它们不会跳跃?我知道简单的解决方案只是给出一个固定的高度,但有些文本只是一个衬里,那些会有更大的差距,所以我认为这对我来说并不是很理想。

标签: androidandroid-jetpack-compose

解决方案


要计算 a 的高度LazyRow,您需要知道元素的所有尺寸。一个直接的解决方案是将它们全部放在LazyRowusing下Box,在这种情况下,大小将由它们中的最大值决定。

但是这种解决方案需要大量资源,尤其是在您有很多对象的情况下。相反,我建议您同时限制info最大title行数,例如 2 条,并计算最大大小,因为这两个文本都将具有最大行数。

@Composable
fun TopicList(topicList: List<Topics>) {
    Column {
        topicList.forEach { topic ->
            val showList = topic.shows
            Column {
                Text(text = topic.title)
                Box {
                    ShowCell(
                        placeholderShow,
                        modifier = Modifier.alpha(0f)
                    )
                    LazyRow(
                        horizontalArrangement = Arrangement.spacedBy(10.dp)
                    ) {
                        items(showList) { show ->
                            ShowCell(show)
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun ShowCell(
    show: Show,
    modifier: Modifier = Modifier
) {
    Column(
        modifier
            .width(200.dp)
    ) {
        Image(
            painter = rememberImagePainter(show.image),
            contentDescription = "...",
            contentScale = ContentScale.Crop,
            modifier = Modifier.aspectRatio(2f)
        )
        Text(
            show.title,
            fontSize = 20.sp,
            maxLines = titleMaxLines,
            overflow = TextOverflow.Ellipsis,
        )
        Text(
            text = show.info,
            maxLines = infoMaxLines,
            overflow = TextOverflow.Ellipsis,
        )
    }
}

private const val titleMaxLines = 2
private const val infoMaxLines = 2
private val placeholderShow = Show(
    image = "",
    title = List(titleMaxLines) { '\n' }.joinToString(separator = ""),
    info = List(titleMaxLines) { '\n' }.joinToString(separator = ""),
)

结果:


推荐阅读