int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
Here is an improved (more effective, less memory usage, less code, updates ViewHolder with the current extent of its visibility) Kotlin version of Vishal Sanghani's answer:
recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
val layoutManager = recycler.layoutManager as LinearLayoutManager
val firstPosition = layoutManager.findFirstVisibleItemPosition()
val lastPosition = layoutManager.findLastVisibleItemPosition()
val globalVisibleRect = Rect()
val itemVisibleRect = Rect()
recycler.getGlobalVisibleRect(globalVisibleRect)
for (pos in firstPosition..lastPosition) {
val view = layoutManager.findViewByPosition(pos)
if (view != null && view.height > 0 && view.getGlobalVisibleRect(itemVisibleRect)) {
val visibilityExtent = if (itemVisibleRect.bottom >= globalVisibleRect.bottom) {
val visibleHeight = globalVisibleRect.bottom - itemVisibleRect.top
Math.min(visibleHeight.toFloat() / view.height, 1f)
} else {
val visibleHeight = itemVisibleRect.bottom - globalVisibleRect.top
Math.min(visibleHeight.toFloat() / view.height, 1f)
}
val viewHolder = recycler.findViewHolderForAdapterPosition(pos) as ViewHolder
viewHolder.setVisibilityExtent(visibilityExtent)
// if percentage is needed...
val percentage = visibilityExtent * 100
}
}
}
})