I have a few thousand items that I need to display in a grid. They are divided in categories, which I'd like to be collapsible.

I thought the most efficient way to achieve this would be by using a single LazyVerticalGrid where I place the section headers as items with GridItemSpan(this.maxLineSpan), while I add and remove items between them as I expand/collapse them. I did this and it works well and very smooth.

LazyVerticalGrid(
    modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp),
    verticalArrangement = Arrangement.spacedBy(20.dp),
    columns = GridCells.Fixed(5),
) {
  viewState.sections.forEach { section ->
    header { InventorySectionHeader(section = section, intent = intent) }
    if (!section.collapsed) {
      items(items = section.items, key = { it.id }) { item ->
        InventorySectionItem(item = item, intent = intent)
      }
    }
  }
}

However, I'd also like to animate the opening/collapsing of these sections, and it has been a headache. Simply wrapping the content of items() with AnimatedVisibility does not work, because even when collapsed items() is still executed and the cells, even if empty, still take up some space, making the headers very far apart from each other.

LazyVerticalGrid(
    modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp),
    verticalArrangement = Arrangement.spacedBy(20.dp),
    columns = GridCells.Fixed(5),
) {
  viewState.sections.forEach { section ->
    header { InventorySectionHeader(section = section, intent = intent) }
    items(items = section.items, key = { it.id }) { item ->
      AnimatedVisibility(
          visible = !section.collapsed,
          enter = expandVertically(expandFrom = Alignment.Top),
          exit = shrinkVertically(shrinkTowards = Alignment.Top)) {
        InventorySectionItem(item = item, intent = intent)
      }
    }
  }
}

I found that I could add Modifier.animateItem() to the content of items(), but this only seem to support fadeIn/fadeOut effects and I couldn't for the life of me make those header items animate to position this way.

Of course, I could get the desired result by making a normal column and using multiple lazy grids for the content of each section, but when I tried it the performance degraded visibly so I would rather go without animation than that.

Anything else I could try?

Source: View source