简体   繁体   English

使 Compose LazyColumn 的最后一项填满屏幕的其余部分

[英]Make last Item of the Compose LazyColumn fill rest of the screen

There is a regular list with some data and LazyColumn for showing it.有一个包含一些数据的常规列表和用于显示它的 LazyColumn。

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

Simplified ListItem looks like:简化的ListItem看起来像:

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

I need to set the footer's item (last in list) height to fill screen if there is not enough items for that.如果没有足够的项目,我需要设置页脚的项目(列表中的最后一个)高度以填充屏幕。 It's easy to find last item and provide some flag to ListItem(item: SomeItem, isLast: Boolean) , but I don't know how to set the item's height to achieve my goal.很容易找到最后一个项目并向ListItem(item: SomeItem, isLast: Boolean)提供一些标志,但我不知道如何设置项目的高度以实现我的目标。 Did anyone faced this problem?有人遇到过这个问题吗?

It's almost the same question as was asked here about RecyclerView .这与这里关于RecyclerView的问题几乎相同。 And the image from that question illustatrates it.该问题的图像说明了这一点。

在此处输入图像描述

If your items are all same height and you have have info of how tall they are via static height or using Modifier.onSizeChanged{} you can do this by getting height of the LazyColumn using BoxWithConstraints maxHeight or rememberLazyListState().layoutInfo.viewportSize如果您的项目都是相同的高度,并且您通过静态高度或使用Modifier.onSizeChanged{}了解它们的高度,您可以通过使用BoxWithConstraints maxHeight 或rememberLazyListState().layoutInfo.viewportSize获取 LazyColumn 的高度来做到这一点

@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)
                    )
                }
            }
        }
    }
}

If you don't know total height until last item you will need to use SubcomposeLayout with list that doesn't contain last item and pass LazyColumn height- (items.size-1) total height as your last item's height.如果您直到最后一项才知道总高度,则需要将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 }

And use it as并将其用作

@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)
                    )
                }
            }
        }
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使 RecyclerView 中的最后一个 Item / ViewHolder 填充屏幕的其余部分或具有最小高度 - Make last Item / ViewHolder in RecyclerView fill rest of the screen or have a min height 在 jetpack compose LazyColumn 中获取最后一个可见项目索引 - Get last visible item index in jetpack compose LazyColumn Compose LazyColumn select 一项 - Compose LazyColumn select one item 如果 LazyColumn 为空,则将 LazyColumn 项目推送到屏幕末尾 - Push a LazyColumn item to end of screen if the LazyColumn is empty Jetpack Compose LazyColumn 项目在 stickyHeader 上滚动并且不滚动到最后一个项目 - Jetpack Compose LazyColumn items scroll over stickyHeader and does not scroll to last item 最后一个元素在 LazyColumn 中不可见。 喷气背包组成 - The last elements are not visible in LazyColumn. Jetpack Compose 如何在 jetpack compose 的 LazyColumn 中添加项目? - How to add item in LazyColumn in jetpack compose? Jetpack Compose LazyColumn 以编程方式滚动到项目 - Jetpack Compose LazyColumn programmatically scroll to Item LazyColumn 中隐藏的底部项目 - Jetpack Compose - Hidden bottom item in LazyColumn - Jetpack Compose 如何在 LazyColumn jetpack compose 的底部粘贴项目 - How to stick item at bottom in LazyColumn jetpack compose
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM