Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find percentage of each visible item in recycleview

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

like image 975
Muhammad chhota Avatar asked Sep 15 '16 05:09

Muhammad chhota


4 Answers

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
        }
     }
})
like image 182
Sahil Kansal Avatar answered Oct 20 '22 11:10

Sahil Kansal


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:

enter image description here

like image 28
Vishal Sanghani Avatar answered Oct 21 '22 17:10

Vishal Sanghani


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);
like image 9
Nikhil Avatar answered Oct 21 '22 19:10

Nikhil


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

            }
        }
    }
})
like image 8
a.ch. Avatar answered Oct 21 '22 19:10

a.ch.