首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Jetpack撰写: LazyRow onScrollListener

Jetpack撰写: LazyRow onScrollListener
EN

Stack Overflow用户
提问于 2022-12-02 00:00:17
回答 2查看 63关注 0票数 1

我想知道是否有一种方法或资源可供我参考,以便在滚动项目时对LazyRow产生副作用?副作用基本上是调用viewModel中的一个函数来更改列表状态的状态。

  • 只有当当前
  • 滚动后的firstVisibleItemIndex与未执行的副作用不同时,才能执行副作用,该项没有完全滚动,我正在实现具有快速行为

的全屏LazyRow项。

到目前为止,我已经尝试过NestedScrollConnection

代码语言:javascript
复制
class OnMoodItemScrolled : NestedScrollConnection {
    override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
        viewModel.fetchItems()
        return super.onPostFling(consumed, available)
    }
}

上面的问题是,副作用无论如何都要执行--尽管滚动后显示的项目与滚动之前相同。

我还试图按以下方式收集listState交互

代码语言:javascript
复制
val firstVisibleItem: Int = remember { sectionItemListState.firstVisibleItemIndex }
    sectionItemListState.interactionSource.collectIsDraggedAsState().let {
        if (firstVisibleItem != sectionItemListState.firstVisibleItemIndex) {
            viewModel.fetchItems()
        }
    }

上面的问题是,副作用将被执行,第二次可合成是第一次。

EN

回答 2

Stack Overflow用户

发布于 2022-12-02 09:02:33

您可以使用获取有关第一个可见项的信息,并存储此值。当值更改时,项目将向上滚动。

类似于:

代码语言:javascript
复制
@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
}

然后:

代码语言:javascript
复制
val state = rememberLazyListState()
var index = state.itemIndexScrolledUp()

DisposableEffect(index){

     if (index != -1) {
          //...item is scrolled up
     }

      onDispose {  }   
}


LazyColumn(
        state = state,
){
  //...
}
票数 3
EN

Stack Overflow用户

发布于 2022-12-02 11:32:46

我用一个有两个键的LaunchedEffect解决了我的问题。

代码语言:javascript
复制
val sectionItemListState = rememberLazyListState()
val flingBehavior = rememberSnapFlingBehavior(sectionItemListState)
var previousVisibleItemIndex by remember {
    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
    }
}

使用currentVisibleItemIndexcurrentVisibleItemScrollOffset作为键将确保只要其中一个更改,就会触发LaunchedEffect。此外,检查previousVisibleItemIndex是否与currentVisibleItemIndex不同,将确保只有在可见项发生更改时才触发此效果。但是,如果使用已经部分滚动,那么这个条件将是真正的也是,而且由于我有抓拍效果,它将回到以前的位置。这将导致触发效应两次。为了确保只有在实际上是滚动到下一个/先前完全可见的位置时才触发效果,我们需要依赖scrollOffset

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74649453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档