有一个包含一些数据的常规列表和用于显示它的懒散列.

LazyColumn {
    items (list) { item ->
        ListItem(item)
    }
}

简化ListItem看起来像:

@Composable
fun ListItem(item: SomeItem) {
    Row(
       modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Min)
    ) {
        //Some widgets
    }
}

如果没有足够的项目,我需要设置页脚的项目(列表中最后一个)高度来填充屏幕.很容易找到最后一个项目,并提供一些标志到ListItem(item: SomeItem, isLast: Boolean),但我不知道如何设置项目的高度,以实现我的目标.有人面临过这个问题吗?

这几乎与我们在这里提出的RecyclerView个问题相同.这个问题的图像说明了这一点.

enter image description here

推荐答案

如果您的项目都是相同的高度,并且通过静态高度或使用Modifier.onSizeChanged{},您可以通过使用BoxWithConstraints maxHeight或rememberLazyListState().layoutInfo.viewportSize获得懒散列的高度信息

@Composable
private fun ListComposable() {

    val myItems = mutableListOf<String>()
    repeat(4) {
        myItems.add("Item $it")
    }


    BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
        LazyColumn(
            modifier = Modifier
                .fillMaxSize()
                .border(2.dp, Color.Cyan)
        ) {
            itemsIndexed(myItems) { index: Int, item: String ->

                if (index == myItems.size - 1) {
                    Text(
                        text = item,
                        modifier = Modifier
                            .fillMaxWidth()
                            .height((maxHeight - 50.dp * (myItems.size - 1)).coerceAtLeast(50.dp))
                            .background(Color.Green)
                    )
                } else {
                    Text(
                        text = item,
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                            .background(Color.Red)
                    )
                }
            }
        }
    }
}

如果直到最后一项才知道总高度,则需要使用SubcomposeLayout和不包含最后一项的列表,并将LazyColumn height- (items.size-1) total height作为最后一项的高度.

@Composable
fun DimensionMeasureSubcomposeLayout(
    modifier: Modifier = Modifier,
    mainContent: @Composable () -> Unit,
    dependentContent: @Composable (IntSize, Constraints) -> Unit
) {

    SubcomposeLayout(modifier = modifier) { constraints ->

        // Subcompose(compose only a section) main content and get Placeable
        val mainPlaceables: List<Placeable> = subcompose(SlotsEnum.Main, mainContent)
            .map {
                it.measure(constraints)
            }

        // Get max width and height of main component
        var maxWidth = 0
        var maxHeight = 0

        mainPlaceables.forEach { placeable: Placeable ->
            maxWidth += placeable.width
            maxHeight = placeable.height
        }

        val maxSize = IntSize(maxWidth, maxHeight)

        val dependentPlaceables = subcompose(SlotsEnum.Dependent) {
            dependentContent(maxSize, constraints)
        }.map {
            it.measure(constraints)
        }

        layout(constraints.maxWidth, constraints.maxHeight) {
            dependentPlaceables.forEach { placeable: Placeable ->
                placeable.placeRelative(0, 0)
            }
        }
    }
}

enum class SlotsEnum { Main, Dependent }

并将其用作

@Composable
private fun SubcomposeExample() {
    val myItems = mutableListOf<String>()
    repeat(15) {
        myItems.add("Item $it")
    }

    val subList = myItems.subList(0, myItems.size - 1)
    val lasItem = myItems.last()

    val density = LocalDensity.current

    DimensionMeasureSubcomposeLayout(
        modifier = Modifier,
        mainContent = {
            LazyColumn(
                modifier = Modifier.fillMaxWidth()
            ) {
                items(subList) { item: String ->
                    Text(
                        text = item,
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                            .background(Color.Red)
                    )
                }
            }
        },
        dependentContent = { intSize, constraints ->

            val lastItemHeight = with(density) {
                (constraints.maxHeight - intSize.height).toDp().coerceAtLeast(50.dp)
            }
            LazyColumn(modifier = Modifier.fillMaxWidth()) {
                if (myItems.size > 1) {

                    items(subList) { item: String ->
                        Text(
                            text = item,
                            modifier = Modifier
                                .fillMaxWidth()
                                .height(50.dp)
                                .background(Color.Red)
                        )
                    }
                }

                item {
                    Text(
                        text = lasItem,
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(lastItemHeight)
                            .background(Color.Green)
                    )
                }
            }
        }
    )
}

Android相关问答推荐

Android配置设置. gradle不同应用风格

Android应用程序中的背景问题

Hilt+Worker NoSuchMethodException:<;init>;[class android.content.Context,class androidx.work.WorkerParameters]

未解析的引用:视图模型

在 kotlin 上向适配器添加绑定视图功能

使用 List 和 LazyColumn 重新组合所有项目

如何在另一个函数中初始化主类参数? (我是初学者)代码推荐

如何在 Jetpack Compose 中对数据类进行 Parcelize

如何删除 Jetpack Compose 中按钮的左边框?

NFC getNdefMessage 在 Android 13 上写入标签后返回 null

无法通过 retrofit 解析对 kotlin 数据类的 xml 响应

Jetpack Compose 重组竞争条件

如何在 Android 上移动 EditText 上的图标?

Kotlin Coroutines Dispatchers.IO 没有创建预期的线程

如何将新的 ComponentActivity 与 ViewBinding 和其他旧的 AppCompatActivity 组件一起使用

Jetpack compose 绘制形状

Android 应用程序在启动时自动启动

可扩展性 Qt 5.15 Android

如何删除 Ktor 客户端 2.0.0 的默认标头

自定义布局忽略可组合的大小