How to make a LazyColumn item occupy the remaining height on Jetpack Compose

3.9k Views Asked by At

Can I make a item on LazyColumn occupy only the remaining height available? I'm I tried to use fillParentMaxSize but it make the item as the same size of the LazyColumn, so i can't put another item at the top of the list, like a header that I want to scroll with the content.

Sample code

@Composable
fun LazyColumnTest() {
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        item {
            Column {
                Text(text = "This is a title", style = MaterialTheme.typography.h4)
                Text(text = "With a subtitle", style = MaterialTheme.typography.subtitle1)

            }
        }
        item {
            OtherLayout(modifier = Modifier.fillParentMaxHeight())
        }
    }
}

@Composable
fun OtherLayout(modifier: Modifier = Modifier) {
    Box(modifier = modifier.fillMaxSize()) {
        Icon(
            Icons.Default.Close,
            contentDescription = null,
            modifier = Modifier
                .size(150.dp)
                .align(Alignment.TopCenter)
        )
        Button(
            onClick = { /*TODO*/ },
            modifier = Modifier
                .padding(bottom = 16.dp)
                .align(Alignment.BottomCenter)
        ) {
            Text(text = "Button at bottom")
        }
    }
}

Here is the current result. The button is outside the screen, so I need to scroll to see it. sample


Update

In the example above, the idea is to use this OtherLayout like a state. I can show the items or this OtherLayout that has a button at bottom, like a retry button. I can do about the same layout on view system if I add fillViewport="true" on a ScrollView. It's possible to add a gravity="bottom" on another view and it will stay at the bottom of screen.

I will add a new example here with the header/footer layout to see if I can explain better.

@Composable
fun LazyColumnTest() {
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        item {
            // need to scroll with the content
            Header()
        }
        items(2) { position ->
            Text(text = "Item $position")
        }
        item {
            // need to stay at bottom if the items not fill the screen
            // and scroll with the content if has a lot of items
            Footer(modifier = Modifier)
        }
    }
}

@Composable
private fun Header() {
    Column {
        Text(text = "This is a title", style = MaterialTheme.typography.h4)
        Text(text = "With a subtitle", style = MaterialTheme.typography.subtitle1)
    }
}

@Composable
fun Footer(modifier: Modifier = Modifier) {
    Column(modifier = modifier.fillMaxWidth()) {
        Text(text = "This is a default footer that cannot be changed")
        Button(
            onClick = { /*TODO*/ },
            modifier = Modifier
                .padding(bottom = 16.dp)
        ) {
            Text(text = "With a button")
        }
    }
}

in this example I need that header and footer scrolls with the content, but if the items not fill the entire screen, the footer remains at bottom of the screen.

sample2

1

There are 1 best solutions below

5
Gabriele Mariotti On

Using the item function you are adding another item to the scrollable content of the LazyColumn.

If you want that the LazyColumn occupies only the remaining height available, and the footer that doesn't scroll with the list, you can move the footer out of the LazyColumn and apply the weight modifier to the LazyColumn.

Something like:

Column(){
    Header()

    LazyColumn(Modifier.weight(1f)) {
        //....
    }

    Footer() //your Box
}

In your case:

Column {

    //Header
    Box(Modifier.fillMaxWidth().height(30.dp).background(Red))

    LazyColumn(Modifier.weight(1f)) {
        items(itemsList){
            Text("Item $it")
        }
    }

    //Footer
    OtherLayout()
}

With:

@Composable
fun OtherLayout(modifier: Modifier = Modifier) {
    Box(modifier = modifier.fillMaxWidth()) {
        //..
    }
}

enter image description here