[英]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.