【问题标题】:How to check visibility of list item in Jetpack Compose如何检查 Jetpack Compose 中列表项的可见性
【发布时间】:2021-09-21 19:05:29
【问题描述】:

React NativeFlatList有一个属性viewabilityConfigCallbackPairs可以在其中设置:

viewabilityConfig: {
    itemVisiblePercentThreshold: 50,
    waitForInteraction: true,
  }

以 50% 的阈值和交互或滚动后检测列表的可见项。

Jetpack Compose 也有类似的东西吗?

LazyListState 有一些布局信息。但我想知道这个用例是否有任何内置组件/属性。

编辑

我有一个卡片视图列表,我想检测哪些卡片项目(至少 50% 的卡片可见)在显示器上可见。但只有当卡片被点击或列表被用户滚动时才需要检测。

【问题讨论】:

  • 你有布局信息,对于任何可见性信息来说已经足够了。显示中间项时需要回调吗?
  • 你如何做不同的百分比阈值?另外,布局信息不能给我们交互信息
  • 交互信息是什么?您是否需要知道视图是通过编程方式滚动还是通过用户触摸滚动?
  • 是的,按用户。例如,当它被滚动或点击时
  • 点击了什么?一些可以滚动视图的按钮?我不熟悉react native,所以我不知道waitForInteraction负责什么。请为您的问题添加详细说明,以便没有反应本机知识的每个人都可以理解您的问题。

标签: android android-jetpack-compose


【解决方案1】:

可以使用LazyListState获取具有一定阈值的当前可见项目的更新列表。

LazyListState 公开当前可见项目List<LazyListItemInfo> 的列表。很容易计算 visibility percent 使用 offsetsize 属性,从而将过滤器应用于 visibility >= threshold 的可见列表。

LazyListItemInfo 具有index 属性,可用于将LazyListItemInfo 映射到传递给LazyColumn 的列表中的实际数据项。

fun LazyListState.visibleItems(itemVisiblePercentThreshold: Float) =
    layoutInfo
        .visibleItemsInfo
        .filter {
            visibilityPercent(it) >= itemVisiblePercentThreshold
        }

fun LazyListState.visibilityPercent(info: LazyListItemInfo): Float {
    val cutTop = max(0, layoutInfo.viewportStartOffset - info.offset)
    val cutBottom = max(0, info.offset + info.size - layoutInfo.viewportEndOffset)

    return max(0f, 100f - (cutTop + cutBottom) * 100f / info.size)
}

用法

val list = state.visibleItems(50f) // list of LazyListItemInfo

这个列表必须首先映射到LazyColumn中的对应项目。

val visibleItems = state.visibleItems(50f)
            .map { listItems[it.index] }

@Composable
fun App() {
    val listItems = remember { generateFakeListItems().toMutableStateList() }

    val state = rememberLazyListState()

    LazyColumn(Modifier.fillMaxSize(), state = state) {
        items(listItems.size) {
            Item(listItems[it])
        }
    }

    val visibleItems = state.visibleItems(50f)
        .map { listItems[it.index] }

    Log.d(TAG, "App: $visibleItems")
}

fun generateFakeListItems() = (0..100).map { "Item $it" }

【讨论】:

  • 谢谢。赞成。我也最终使用了列表状态并自己实现了
  • 请让我知道此答案中是否缺少任何内容以被接受。谢谢!
  • Kotlin 小提示:对于 visibilityPercent 中的所有用法,您可以使用 maxOf() 而不是 max() :-)
  • layoutInfo.visibleItemsInfo 强制重组,进入无限重组:issuetracker.google.com/issues/216499432
  • 这个想法很好,但是当你在 LazyColumn 中有多个项目变得困难时,也应该有一个检查以避免每秒调用它
猜你喜欢
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2023-04-03
  • 2017-03-25
相关资源
最近更新 更多