androidandroid-jetpack-composelazycolumn

Android Jetpack Compose - Saving a LazyListState's firstVisibleItemIndex in one Composable Function for another Function to scroll to


Scenario: I have two similar Composable functions that display similar lists of data via LazyColumns, each having their own rememberLazyListState variables.

@Composable
fun ListA(listData: List<TypeA>)
{
    LazyColumn {
        items(listData) {
            LazyColumnItem(data: TypeA)
        }
    }
}

@Composable
fun ListB(listData: List<TypeB>) 
{
    LazyColumn {
        items(listData) {
            LazyColumnItem(data: TypeB)
        }
    }
}

Something along those lines; the code is a bit more complicated that this with recomposition after some State values change outside of these composable functions; state that determine which List composable to display, either TypeA or TypeB lists. Assume both lists have the same itemCount or listSize.

While I notice that the list saves its position or state when modifying outside state that causes recomposition with the same composable; modifying state that changes the composable displayed into the other composable (ie, TypeB list composable was displayed using TypeB's composable function, now I want to show TypeA list composable using TypeA's composable function), the list position is reset to 0. This I understand, but I am trying to do it so that I can change the composable function used and scroll to the position the previous list was at.

I've tried creating function parameters to pass the LazyListState's firstVisibleItemIndex to the host function for these composables inside one of Compose's effect blocks, fair warning, I'm still learning Compose and Effect blocks but I'm not sure if this is the correct approach:

LaunchedEffect(key1 = "key) {
    lazyListState.animateScrollToItem(index)
    functionNameToPassIndex(index: Int)
}

The above code block doesn't pass the index up properly to save in a rememberSavable variable holding the index as state.

I guess I'm mainly asking for possible guidance on how to do this, while I'm figuring it out myself too. Any tips or steps would be appreciated over a direct solution.


Solution

  • Have you tried using a single LazyListState for both composables?

    In a very simple example such as:

    var bool by remember { mutableStateOf(true) }
    val listState = rememberLazyListState()
    
    Column(modifier = Modifier.fillMaxSize()) {
        Button(onClick = { bool = !bool }) {
            Text(text = "Swap List")
        }
        if (bool) {
            ListA(listData = items, listState = listState, modifier = Modifier.weight(1f))
        } else {
            ListB(listData = items, listState = listState, modifier = Modifier.weight(1f))
        }
    }
    

    It seems to work quite well, even if the items are different sizes.