我有一个包含项目的惰性行。现在,我想对每当用户滚动惰性行时在视口中完全可见的项目进行 API 调用。
我尝试过以下代码:
listState = rememberLazyListState()
LaunchedEffect(listState){
snapshotFlow { listState.firstVisibleItemIndex }
.collectLatest{
Log.d("printed Item", listState.firstVisibleItemIndex.toString())
}}
这段代码的问题是:
谁能告诉我如何解决我的问题?
有关可见项目的所有信息均可在
state.layoutInfo
中找到。要检查该项目是否可见,您需要根据视口大小比较第一个和最后一个项目的位置(所有其他项目肯定都会可见)。
要仅对更改的单元格启动重组,您可以再次使用
derivedStateOf
中的 item
将索引转换为特定的布尔状态。
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) { index ->
val isVisible by remember(index) {
derivedStateOf {
fullyVisibleIndices.contains(index)
}
}
Text(
index.toString(),
modifier = Modifier
.background(if (isVisible) Color.Green else Color.Transparent)
.padding(30.dp)
)
}
}
另一种解决方案是使用可见卡的偏移量
val currentVisibleIndex = remember {
derivedStateOf {
val visibleItem = listState.layoutInfo.visibleItemsInfo
visibleItem.firstOrNull()?.index?.let { currentIndex ->
if (visibleItem.firstOrNull()?.offset!! == 0) {
currentIndex
} else if (visibleItem.firstOrNull()?.offset!! > LEFT_OFFSET) { //value should be checked based on your card size ex: -234 means card is partially visible on screen
if (currentIndex < list.size) {
currentIndex + 1
} else {
currentIndex
}
} else if (visibleItem.firstOrNull()?.offset!! > RIGHT_OFFSET){
if (currentIndex-1 >= 0) {
currentIndex - 1
} else {
currentIndex
}
} else {
currentIndex
}
}
}
}
您可以根据您的卡片大小通过日志查看LEFT和RIGHT_OFFSET值。
也许您可以尝试在视频刚出屏幕时暂停视频?
这些允许视图组件不用担心列表(容器)。
要实现此功能,您应该添加
androidx.lifecycle:lifecycle-runtime-compose:2.7.+
LifecycleResumeEffect(Unit) { onPauseOrDispose { viewModel.pause() } }
但是,如果您在一个屏幕上同时显示多个视频,如何正确暂停一个视频并保留另一个视频 - 这仍然是一个开放的话题