[英]Jetpack Compose: LazyRow onScrollListener
我想知道是否有一种方法或资源可以参考,以便在滚动项目时对LazyRow
产生副作用? 副作用基本上是在 viewModel 中调用 function 来更改列表 state 的 state。
LazyRow
项目到目前为止,我已经尝试过NestedScrollConnection
class OnMoodItemScrolled : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
viewModel.fetchItems()
return super.onPostFling(consumed, available)
}
}
上面的问题是无论如何都会执行副作用 - 即使滚动后显示的项目与滚动前相同。
我还尝试按以下方式收集 listState 交互
val firstVisibleItem: Int = remember { sectionItemListState.firstVisibleItemIndex }
sectionItemListState.interactionSource.collectIsDraggedAsState().let {
if (firstVisibleItem != sectionItemListState.firstVisibleItemIndex) {
viewModel.fetchItems()
}
}
上面的问题是副作用将在可组合项第一次组合时执行。
您可以使用LazyListState#firstVisibleItemIndex
获取有关第一个可见项目的信息并存储此值。 当值更改时,项目将向上滚动。
就像是:
@Composable
private fun LazyListState.itemIndexScrolledUp(): Int {
var previousIndex by remember(this) { mutableStateOf(firstVisibleItemIndex) }
return remember(this) {
derivedStateOf {
if (firstVisibleItemIndex > previousIndex) {
//scrolling up
previousIndex
} else {
- 1
}.also {
//Update the previous index
previousIndex = firstVisibleItemIndex
}
}
}.value
}
接着:
val state = rememberLazyListState()
var index = state.itemIndexScrolledUp()
DisposableEffect(index){
if (index != -1) {
//...item is scrolled up
}
onDispose { }
}
LazyColumn(
state = state,
){
//...
}
我使用带有 2 个键的LaunchedEffect
解决了我的问题。
val sectionItemListState = rememberLazyListState()
val flingBehavior = rememberSnapFlingBehavior(sectionItemListState)
var previousVisibleItemIndex by rememberSaveable {
mutableStateOf(0)
}
val currentVisibleItemIndex: Int by remember {
derivedStateOf { sectionItemListState.firstVisibleItemIndex }
}
val currentVisibleItemScrollOffset: Int by remember {
derivedStateOf { sectionItemListState.firstVisibleItemScrollOffset }
}
LaunchedEffect(currentVisibleItemIndex, currentVisibleItemScrollOffset) {
if (previousVisibleItemIndex != currentVisibleItemIndex && currentVisibleItemScrollOffset == 0) {
// The currentVisible item is different than the previous one && it's fully visible
viewModel.fetchItems()
previousVisibleItemIndex = currentVisibleItemIndex
}
}
使用currentVisibleItemIndex
和currentVisibleItemScrollOffset
作为键将确保只要其中一个发生变化就会触发LaunchedEffect
。 此外,检查previousVisibleItemIndex
是否不同于currentVisibleItemIndex
将确保我们仅在可见项目发生变化时才触发此效果。 但是,如果使用已部分滚动,则此条件也将为真,因为我有捕捉效果,它将 go 返回到之前的 position。这将导致两次触发效果。 为了确保我们仅在实际滚动到下一个/上一个完全可见的 position 时才触发效果,我们需要依赖scrollOffset
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.