if i want to change some color based on list scrol...
# compose
m
if i want to change some color based on list scrolling or not, is this the correct approach:
Copy code
var isScrolling by remember {
        mutableStateOf(lazyListState.isScrollInProgress)
    }
    
    LaunchedEffect(key1 = lazyListState){
        snapshotFlow { lazyListState.isScrollInProgress }.collect {
            isScrolling = it
        }
    }
a
Why not use
lazyListState.isScrollInProgress
directly?
m
Ya, i dont know. I saw a similar approach in chris banes pager implementation. And he does the following:
Copy code
LaunchedEffect(item) {
    snapshotFlow { pagerState.currentPage }.collect { page: Int ->        
    }
}
To be honest, i don’t quite know when to use remember vs a simple state variable. Can you point me to the right direction here? still learning
a
I think I'd need to see the surrounding code to have an opinion on that pager implementation 🙂
m
ok, so imagining i am querying some info from the pagerState, for instance:
Copy code
state.layoutInfo.visibleItemsInfo.firstOrNull { it.offset > 0 }?.index
If it produces the same output across recomposition, compose just skips it right? So in that case i don’t need remember right ?
a
Use
mutableStateOf
when you need (a) observability (things recompose/relayout/redraw accordingly if it changes) and/or (b) transactionality (changes made in composition don't become "truth" until the composition or other snapshot successfully commits).
Use
remember
when you need to persist the same value or object across multiple recompositions instead of creating new ones on every recomposition
If you have that expression and you only want to recompose if its final value changes, use
derivedStateOf
so
Copy code
val firstIndex by derivedStateOf {
  state.layoutInfo.visibleItemsInfo.firstOrNull { it.offset > 0 }?.index
}
m
I am using that index inside an item composable in LazyRow
ok, makes sense i guess. Thanks
a
derivedStateOf
returns a state object, so if you don't want to recreate that derived state object every recomposition, you can remember it and key it based on what should cause your code to create a new instance:
Copy code
val firstIndex by remember(state) {
  derivedStateOf {
    state.layoutInfo.visibleItemsInfo.firstOrNull { it.offset > 0 }?.index
  }
}
m
yes. I’m trying to query for the firstVisibleItem, but that attribute of state returns an item with negative offset (my guess is because of the margins). So i need to query using visibleItemInfo. I don’t know if there is a better way
a
items have a negative offset if they're scrolled partially out of the viewport