【问题标题】:How to know items which are fully visible in the view port of a lazy row in jetpack compose?如何知道在jetpack compose中懒惰行的视口中完全可见的项目?
【发布时间】:2022-06-20 18:56:20
【问题描述】:

我有一个包含项目的惰性行。现在我想对在用户滚动惰性行时在视口中完全可见的项目进行 API 调用。

我已经尝试了以下代码:

    listState = rememberLazyListState()
    LaunchedEffect(listState){
    snapshotFlow { listState.firstVisibleItemIndex }
    .collectLatest{
    Log.d("printed Item",  listState.firstVisibleItemIndex.toString())
    }}

这段代码的问题是:

  1. 即使第 2 项占据视口,也不会打印,除非第 1 项完全不可见。
  2. 对于平板电脑,由于它们的大屏幕尺寸,即使屏幕上有 2 个可见项目,也只会对第一个可见项目进行 API 调用。请参阅屏幕截图。

当第一个项目部分可见而第二个项目完全可见时 [1]:https://i.stack.imgur.com/l5QcB.jpg

当第二个图块完全可见而第一个图块完全不可见时 [2]:https://i.stack.imgur.com/6rmiQ.jpg

对于完全可见 2 个项目的平板电脑 [3]:https://i.stack.imgur.com/QYRTI.jpg

谁能告诉我如何解决我的问题?

【问题讨论】:

  • listState.layoutInfo.visibleItemsInfo?
  • @PylypDukhov 你能用完整的代码回答吗,因为我不知道如何使用它来解决问题的逻辑,因为listState.layoutInfo.visibleItemsInfo 导致无限重组并且还返回部分可见的项目在屏幕上显示完全可见的项目。

标签: android android-layout android-jetpack-compose


【解决方案1】:

关于可见项目的所有信息都可以在state.layoutInfo 中找到。要检查项目是否可见,您需要根据视口大小比较第一个和最后一个项目的位置(所有其他项目肯定是可见的)。

val state = rememberLazyListState()
val fullyVisibleIndices: List<Int> by remember {
    derivedStateOf {
        val layoutInfo = state.layoutInfo
        val visibleItemsInfo = layoutInfo.visibleItemsInfo
        if (visibleItemsInfo.isEmpty()) {
            emptyList()
        } else {
            val fullyVisibleItemsInfo = visibleItemsInfo.toMutableList()

            val lastItem = fullyVisibleItemsInfo.last()

            val viewportHeight = layoutInfo.viewportEndOffset + layoutInfo.viewportStartOffset

            if (lastItem.offset + lastItem.size > viewportHeight) {
                fullyVisibleItemsInfo.removeLast()
            }

            val firstItemIfLeft = fullyVisibleItemsInfo.firstOrNull()
            if (firstItemIfLeft != null && firstItemIfLeft.offset < layoutInfo.viewportStartOffset) {
                fullyVisibleItemsInfo.removeFirst()
            }

            fullyVisibleItemsInfo.map { it.index }
        }
    }
}
LazyColumn(
    state = state,
    contentPadding = PaddingValues(30.dp)
) {
    items(100) {
        Text(
            it.toString(),
            modifier = Modifier
                .background(if (fullyVisibleIndices.contains(it)) Color.Green else Color.Transparent)
                .padding(30.dp)
        )
    }
}

不确定您将如何在现实生活中使用此信息,如果您确实需要更新项目视图,出于性能原因,最好将此逻辑移动到每个 item 中,以免触发整个 @987654324 的重组@

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 2021-06-17
    • 2022-09-30
    • 2018-12-06
    相关资源
    最近更新 更多