To get an updating list of currently visible items with a certain threshold LazyListState
can be used.
LazyListState
exposes the list of currently visible items List<LazyListItemInfo>
. It's easy to calculate visibility percent
using
offset
and size
properties, and thus apply a filter to the visible list for visibility >= threshold
.
LazyListItemInfo
has index
property, which can be used for mapping LazyListItemInfo
to the actual data item in the list passed to 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)
}
Usage
val list = state.visibleItems(50f) // list of LazyListItemInfo
This list has to be mapped first to corresponding items in 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 by remember(state) {
derivedStateOf {
state.visibleItems(50f)
.map { listItems[it.index] }
}
}
LaunchedEffect(visibleItems) {
Log.d(TAG, "App: $visibleItems")
}
}
fun generateFakeListItems() = (0..100).map { "Item $it" }