23

How to implement pagination of recyclerview that is within NestedScrollView?

AskNilesh
  • 58,437
  • 15
  • 99
  • 129
Jatin
  • 1,510
  • 2
  • 14
  • 28
  • I tried to implement addOnScrollListener of recyclerview but it calls everytime when I bind my data to recyclerview. It should call on page end only – Jatin Oct 09 '17 at 04:40

3 Answers3

50

Follow this steps :

1. Set nested scrolling enabled false of recycler view.

recyclerView.setNestedScrollingEnabled(false);

2. Add scroll listner to nested scrollview.

 mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
           @Override
           public void onScrollChanged()
           {
                    View view = (View)mScrollView.getChildAt(mScrollView.getChildCount() - 1);

                    int diff = (view.getBottom() - (mScrollView.getHeight() + mScrollView
                                    .getScrollY()));

                    if (diff == 0) {
                       // your pagination code
                    }
           }
  });
AskNilesh
  • 58,437
  • 15
  • 99
  • 129
Vishva Dave
  • 5,037
  • 2
  • 27
  • 51
  • 3
    its calling all pagination at once – Eldhopj Mar 19 '19 at 10:52
  • @Eldhopj May be there is issue in your pagination code. as this works perfect for me. – Vishva Dave Mar 20 '19 at 04:09
  • But When I am using recyclerview inside nestedscrollview, Recyclerview becoming heavy - Skipped frames.After so many scrolls my RecyclerView starting to lag.getting error : Skipped 186 frames! The application may be doing too much work on its main thread. How can I fix this? – user2162130 Feb 05 '21 at 09:23
  • Hi @user2162130 have disabled scrolling of recyclerview ? this can happen when there is both scrolling views. you need to disable scrolling of recyclerview – Vishva Dave Feb 09 '21 at 04:50
  • @VishvaDave Yes I have already disabled scrolling of recyclerview then after that recycler view becoming heavy and lagging. Sometime app is also crashed due to this. – user2162130 Feb 09 '21 at 09:36
  • @user2162130 It's strange issue. as this is the only solution while we use recyclerview inside scrollview. it can be the case that your recyclerview is having some operations i.e timers or loop for rendering data. then it can become heavy if not managed properly then, other then that can try same nested scrolling enabled false from both java file and xml. – Vishva Dave Feb 09 '21 at 10:09
  • @VishvaDave if I remove nestedscrollview then my recyclerview works properly no any lagging, working smoothly but if I use same recyclerview inside nestedscrollview then it's lagging and heavy and after some time it's crash. I have also set nested scroll enabled false from both java and xml file. – user2162130 Feb 09 '21 at 11:14
7

if you are using Kotlin your code will be looks like

 scroll?.viewTreeObserver?.addOnScrollChangedListener {
        val view = scroll.getChildAt(scroll.childCount - 1)
        Timber.d("Count==============${scroll.childCount}")

        val diff = view.bottom - (scroll.height + scroll.scrollY)
        Timber.d("diff==============$diff")

        if (diff == 0) {
            //your api call to fetch data
        }
    }

and last but the not the least set RecyclerView scrolling false

 ViewCompat.setNestedScrollingEnabled(recyclerView, false)
shahid17june
  • 1,129
  • 1
  • 8
  • 14
1

I could get the solution setting OnScrollChangeListener in the nestedScrollView.

The field isLoading should be changed everytime you load the items, for example if you are using retrofit. You could set it as true before It start running and as false when you get the response or the failure.

The field isLastPage should be changed everytime you get items and check if this page was the last one.

I'm using kotlin.

private var isLoading = false

private var isLastPage = false

nestedScrollView.setOnScrollChangeListener { v: NestedScrollView?, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int ->

            val nestedScrollView = checkNotNull(v){
                return@setOnScrollChangeListener
            }

            val lastChild = nestedScrollView.getChildAt(nestedScrollView.childCount - 1)

            if (lastChild != null) {

                if ((scrollY >= (lastChild.measuredHeight - nestedScrollView.measuredHeight)) && scrollY > oldScrollY && !isLoading && !isLastPage) {

                    //get more items
                }
            }
        }

And of course you need to set the field isNestedScrollingEnabled as false

myRecyclerView.isNestedScrollingEnabled = false
jmarkstar
  • 1,245
  • 14
  • 21