Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I fill the remaining space in the Lazy Column when using Android Compose?

Tags:

android

kotlin

I've been using Compose recently in my project. However, I felt that LazyColumn is very different from xml in the way it works.

Especially when creating a list, I want to fill the remaining space between topBar and footer, but I can't find a way.

Below is a simplified version of the page I want to implement.

enter image description here

The topBar is fixed to the top, and the list of items is drawn below it. And finally, FooterView is attached. The scrollable area includes itemList and FooterView.

When using xml, I put RecyclerView in nestedScrollView and set weight to 1. Then the area of ​​the list is expanded and the footer is automatically pushed to the end.

However, when using LazyColumn in Compose, the scope of the list cannot be expanded due to LazyListScope.

If lazyColumn is not used and weight is set to 1, part of the item list is not visible. Alternatively, if lazyColumn is not used and no weight is given, the footer is not attached to the bottom.

Lately I've been spending most of my time trying to solve this problem. I would like some help on how to implement such a layout. Thank you.

like image 879
devnunu Avatar asked Dec 04 '25 15:12

devnunu


2 Answers

I found another option which does recycle the items:

    // This will only get called if list doesn't fill the screen.
    @Stable
    val ListLastItemBottomArrangement = object : Arrangement.Vertical {
        override fun Density.arrange(totalSize: Int, sizes: IntArray, outPositions: IntArray) {
            val consumedSize = sizes.fold(0) { a, b -> a + b }
            val remainingSize = (totalSize - consumedSize).coerceAtLeast(0)

            var current = 0
            sizes.forEachIndexed() { index, it ->
                if(index == sizes.lastIndex) {
                    // Move last item to bottom
                    outPositions[index] = current + remainingSize
                } else {
                    outPositions[index] = current
                    current += it
                }
            }
        }
    }

The normal outPositions is copied from Arrangement.Top, so it will work like it normally would. But I added a check for the last index which will move it's position down with whatever remaining size there is so it's always at the bottom. However, this function will only be called if the LazyColumn doesn't scroll. So when it scrolls it will behave like it normally would.

like image 54
Kevin van Mierlo Avatar answered Dec 07 '25 04:12

Kevin van Mierlo


You can set verticalArrangement to Arrangement.SpaceBetween and put all top views in one item and all below views in another one.
Unfortunately your items probably won't be recycled in this approach.

Column(modifier = Modifier.fillMaxSize()) {
    TopBar()
    LazyColumn(
        verticalArrangement = Arrangement.SpaceBetween,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .fillMaxWidth()
            .weight(1F)
    ) {
        item {
          //All top views
        }
        item {
          //Bottom views
        }
    }
}
like image 20
Amir Avatar answered Dec 07 '25 03:12

Amir