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.

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.
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.
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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With