androidkotlinlayoutandroid-jetpack-compose

Connect two LazyGrid layouts


I have an app that shows a list of projects and filters for them. The filters are above the projects and can be hidden. The problem is that it is not clear how to use LazyGrid to hide these filters holistically as a group. In a perfect world I would like to do it this way:

LazyVerticalGrid {
   item { ShowFilters() }
   AnimatedVisibility(visible = isShowing) {
       item { FilterOne() }
       item { FilterTwo() }
       ...
       item { FilterN() }
   }
   items(someData.projects) { ... }
}

In reality, however, I had to reinvent the wheel:

Column {
   ShowFilters()
   AnimatedVisibility(visible = isShowing) {
       LazyVerticalGrid {
           item { FilterOne() }
           item { FilterTwo() }
           ...
           item { FilterN() }
       }
   }
   LazyVerticalGrid {
         items(someData.projects) { ... }
   }
}

The problem with this approach is obvious: the page scrolls in different places. Separate scroll for filters, separate scroll for projects. Is there a solution to this problem? Yes, animation for filters is necessary. It is impossible to use scrollable in column because of unknown size of filters and projects (but it may be the only solution).


Solution

  • You can wrap each individual FilterXX() Composable with AnimatedVisibility like this:

    @Composable
    fun FilteredGrid() {
    
        var showFilters by remember {
            mutableStateOf(true)
        }
        var gridItems = remember {
            mutableStateListOf("Item A", "Item B", "Item C", "Item D", "Item E", "Item F")
        }
    
        LazyVerticalGrid(
            columns = GridCells.Fixed(2)
        ) {
            item(span = { GridItemSpan(2) }) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center
                ) {
                    Switch(checked = showFilters, onCheckedChange = { showFilters = !showFilters })
                }
            }
            item(span = { GridItemSpan(2) }) {
                Text(text = "FILTERS")
            }
            item {
                AnimatedVisibility(visible = showFilters) {
                    Text(text = "Filter A")
                }
            }
            item {
                AnimatedVisibility(visible = showFilters) {
                    Text(text = "Filter B")
                }
            }
            item {
                AnimatedVisibility(visible = showFilters) {
                    Text(text = "Filter C")
                }
            }
            item {
                AnimatedVisibility(visible = showFilters) {
                    Text(text = "Filter D")
                }
            }
            item {
                AnimatedVisibility(visible = showFilters) {
                    Text(text = "Filter E")
                }
            }
    
            item(span = { GridItemSpan(2) }) {
                Text(text = "RESULTS")
            }
    
            items(gridItems) {
                Text(text = it)
            }
        }
    }
    

    Output:

    Screenrecording