[英]How to check visibility of list item in Jetpack Compose
React Native
的FlatList
有一个属性viewabilityConfigCallbackPairs
可以设置:
viewabilityConfig: {
itemVisiblePercentThreshold: 50,
waitForInteraction: true,
}
以 50% 的阈值和交互或滚动后检测列表的可见项目。
Jetpack Compose 是否也有类似的东西?
有一些布局信息的LazyListState
。 但我想知道这个用例是否有任何内置组件/属性。
编辑
我有一个卡片视图列表,我想检测哪些卡片项目(至少 50% 的卡片可见)在显示中可见。 但只有当用户点击卡片或滚动列表时才需要检测。
要获取具有特定阈值的当前可见项目的更新列表,可以使用LazyListState
。
LazyListState
公开了当前可见项目的List<LazyListItemInfo>
。 使用offset
和size
属性可以很容易地计算visibility percent
,因此可以将过滤器应用于可见性列表以达到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" }
LazyListState#layoutInfo
包含有关可见项的信息。
由于要应用阈值,因此需要根据视口大小检查第一个和最后一个项目的位置和大小。 所有其他项目肯定是可见的。
请务必注意,由于您正在阅读state
,因此您应该使用derivedStateOf
来避免冗余重组。
就像是:
@Composable
private fun LazyListState.visibleItemsWithThreshold(percentThreshold: Float): List<Int> {
return remember(this) {
derivedStateOf {
val visibleItemsInfo = layoutInfo.visibleItemsInfo
if (layoutInfo.totalItemsCount == 0) {
emptyList()
} else {
val fullyVisibleItemsInfo = visibleItemsInfo.toMutableList()
val lastItem = fullyVisibleItemsInfo.last()
val viewportHeight = layoutInfo.viewportEndOffset + layoutInfo.viewportStartOffset
if (lastItem.offset + (lastItem.size*percentThreshold) > viewportHeight) {
fullyVisibleItemsInfo.removeLast()
}
val firstItemIfLeft = fullyVisibleItemsInfo.firstOrNull()
if (firstItemIfLeft != null &&
firstItemIfLeft.offset + (lastItem.size*percentThreshold) < layoutInfo.viewportStartOffset) {
fullyVisibleItemsInfo.removeFirst()
}
fullyVisibleItemsInfo.map { it.index }
}
}
}.value
}
然后只需使用:
val state = rememberLazyListState()
LazyColumn( state = state ){
//items
}
val visibleItems = state.visibleItemsWithThreshold(percentThreshold = 0.5f)
通过这种方式,您可以获得阈值为 50% 的所有可见项的列表。 您可以使用以下方法观察列表:
LaunchedEffect(visibleItems){
Log.d(TAG, "App: $visibleItems")
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.