LazyColumn With Multi-Header In Jetpack Compose.

Jayant Kumar🇮🇳
3 min readSep 23, 2023
Photo by Kelly Sikkema on Unsplash

In this article we will see how to make multiple headers for Lazy Column in Jetpack compose.

As you can see in the above video , we have a list of items , and all the items have a type (Animal , Flower, Furniture). We will arrange all the items according to their types and also see show/hide the items.

data class Item(
val id: Int,
val name: String,
val type: String
)

val itemList = listOf(
Item(
1, "Tiger", "Animal"
),
Item(
2, "Lion", "Animal"
),
Item(
3, "Deer", "Animal"
),
Item(
4, "Lotus", "Flower"
),
Item(
5, "Sunflower", "Flower"
),
Item(
6, "Rose", "Flower"
),
Item(
7, "Table", "Furniture"
),
Item(
8, "Chair", "Furniture"
),
Item(
9, "Bed", "Furniture"
),
Item(
10, "Monkey", "Animal"
),
)

First we defined the list of data with their type…

@Composable
fun LazyColumnWithMultiHeaderScreen(
modifier: Modifier
) {

// a mutable map variable , which indicate that item is visible or not
var isShow = remember {
mutableStateMapOf<String, Boolean>()
}

// by default we will store true , all the item will be visible
LaunchedEffect(key1 = Unit) {
isShow = isShow.apply {
itemList.associate { item ->
item.type to true
}.also {
putAll(it)
}
}
}

LazyColumn(
modifier = modifier
.padding(20.dp)
.fillMaxSize()
) {
val groupItems = itemList.groupBy { it.type }
groupItems.forEach { (type, items) ->
item {
Row(
modifier = Modifier
.padding(vertical = 15.dp)
.fillMaxWidth()
.toggleable(
value = isShow[type] == true,
onValueChange = {
isShow[type] = it
},
role = Role.Button
)
) {
Row(
modifier = Modifier.weight(1f)
) {
Text(
text = type,
style = MaterialTheme.typography.headlineLarge.copy(
color = Color.Black,
fontWeight = FontWeight.W700
),

)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = "(${items.size})",
style = MaterialTheme.typography.headlineLarge.copy(
color = Color.Black,
),

)
}
Spacer(modifier = Modifier.width(10.dp))
Icon(
if (isShow[type] == true) Icons.Default.KeyboardArrowDown else Icons.Default.KeyboardArrowUp,
contentDescription = null,
modifier = Modifier.align(CenterVertically)
)
}
}
if (isShow[type] == true)
items(items, key = { it.id }) {
Text(
text = it.name, style = MaterialTheme.typography.bodyLarge.copy(
color = Color.DarkGray
),
modifier = Modifier.padding(top = 10.dp)
)
}
}
}

}
  • As you can see in the above code , First we have defined a isShow variable , which is a mutableStateMapOf<String,Boolean> , which store type (Animals , Flowers , Furniture) and their corresponding true/false value, so that it’s easy to keep track , which item we want to show/hide.
  • After that in the LaunchEffect we apply all the type to true , because by default all the item will be visible.
  • Now in the LazyColumn , first we group the items with their type , As you see with the help of groupBy{} kotlin’s in-built function , it will return Map<String, List<Item>> .
  • After that use forEach loop which will return (type,List<Item>) , In the item{} function , just write your header section with hide/show functionality
  • And In the items{} function , pass your List<Item> data , and it will show all the items corresponding to their type

That’s all for today my friends , Hope you enjoyed and learnt something new from this article.

--

--

Jayant Kumar🇮🇳

Hello , My name is Jayant, I am a tech youtuber and software Engineer from India 🇮🇳