int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
All this method is giving which item is visible, but how to find percentage of visible item in Recycleview?
i.e findFirstVisibleItemPosition(); is giving position of first visible item but I want to perform some operation when first is visible more then 50 percentage
Here is more improved and less complex (more effective, less memory usage, less code) in kotlin.
No need do compare item rect with recycler view rect
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()
recycler.getGlobalVisibleRect(globalVisibleRect)
for (pos in firstPosition..lastPosition) {
val view = layoutManager.findViewByPosition(pos)
if (view != null) {
val percentage = getVisibleHeightPercentage(view)
}
}
}
//Method to calculate how much of the view is visible
private fun getVisibleHeightPercentage(view: View): Double {
val itemRect = Rect()
val isParentViewEmpty = view.getLocalVisibleRect(itemRect)
// Find the height of the item.
val visibleHeight = itemRect.height().toDouble()
val height = view.getMeasuredHeight()
val viewVisibleHeightPercentage = visibleHeight / height * 100
if(isParentViewEmpty){
return viewVisibleHeightPercentage
}else{
return 0.0
}
}
})
Override the ScrollChangedListener of recyclerview and add below code in onScollerdChanged, to get the visibility of your row.
if (rvPercentage != null){
LinearLayoutManager layoutManager = ((LinearLayoutManager) rvPercentage.getLayoutManager());
final int firstPosition = layoutManager.findFirstVisibleItemPosition();
final int lastPosition = layoutManager.findLastVisibleItemPosition();
Rect rvRect = new Rect();
rvPercentage.getGlobalVisibleRect(rvRect);
for (int i = firstPosition; i <= lastPosition; i++) {
Rect rowRect = new Rect();
layoutManager.findViewByPosition(i).getGlobalVisibleRect(rowRect);
int percentFirst;
if (rowRect.bottom >= rvRect.bottom){
int visibleHeightFirst =rvRect.bottom - rowRect.top;
percentFirst = (visibleHeightFirst * 100) / layoutManager.findViewByPosition(i).getHeight();
}else {
int visibleHeightFirst = rowRect.bottom - rvRect.top;
percentFirst = (visibleHeightFirst * 100) / layoutManager.findViewByPosition(i).getHeight();
}
if (percentFirst>100)
percentFirst = 100;
mData.get(i).setPercentage(percentFirst);
mAdapter.notifyItemChanged(i);
}
}
It gives you below output:
You need to write addOnScrollListener()
for recyclerview
and inside that write following code where you will get position of firstVisibleItem
and then you can get dimension of that item on each scroll. Just save previous dimension in global variable and compare it with the current dimension and calculate percentage on every scroll change. When you get your desired percentage then perform your operations.
int position = linearLayoutManager.findFirstVisibleItemPosition();
Rect rect = new Rect();
linearLayoutManager.findViewByPosition(position).getGlobalVisibleRect(rect);
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
}
}
}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With