'How can I add a stickyHeader to LazyVerticalGrid like LazyColumn in jetpack compose?

I want to achieve a UI effect like this:

<GridView>
    <Title of Grid content in a single row />
    <Grid content arranged in the form of n * 3 />

    <Title of Grid content in a single row />
    <Grid content arranged in the form of n * 3 />

    <Title of Grid content in a single row />
    <Grid content arranged in the form of n * 3 />
</GridView>

But I am not able to add the row to the LazyColumnGrid.

I tried using the LazyColumnGrid around Column with vertical scroll, but it says it's wrong to nest two scrollable views in the same direction.

Also, I tried to use item{ } on <Title of Grid />, but that made item{ } an item in the gridview, not a single row.

So how can I achieve this in a simple way?



Solution 1:[1]

You can't really create a sticky header with Compose's LazyGrid apis, but you can create a header as follow:


fun LazyGridScope.header(
    content: @Composable LazyGridItemScope.() -> Unit
) {
    item(span = { GridItemSpan(this.maxLineSpan) }, content = content)
}

The code uses the span block with this.maxLineSpan which becomes a full-width header.

So, you can use it like this

LazyVerticalGrid(
    ...
) {
    header {
        Text("Header Title") // or any composable for your single row
    }
    items(count = n * 3) {
        GridItem() 
    }


    header {
        Text("Header Title") // or any composable for your single row
    }
    items(count = n * 3) {
        GridItem() 
    }
    
}

BONUS You can also offset your cells this way

fun LazyGridScope.offSetCells(count: Int) {
    item(span = { GridItemSpan(count) }) {}
}

...

LazyVerticalGrid(
   ...
) {
    offsetCells(count = 3)
}

Solution 2:[2]

The currently available way is to implement it without the nested scrolling at all.

LazyColumn {
    grouped.forEach { (headText, allGrids) ->
        stickyHeader {
            //Sticky Heading
            Text(text = "Starting with $headText");
        }
        items(allGrids) { grid ->
            // Implement <Grid content- n*3 /> without scrolling

            // Method 1: Rows & .forEach{ }
            Row {
             name.forEach { gridItem ->
               // implement gridItem
               Text(
                 gridItem.toString(),
                 modifier = Modifier
                   .border(BorderStroke(2.dp, Color.LightGray))
                   .padding(15.dp)
                   .fillParentMaxWidth(0.3f)
                )
               }
             }

            // Method 2: Using basic Column & Rows
        }
    }
}

Output

header grid layout

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2