RecyclerView ScrollListener inside NestedScrollView
L

4

45

I have an EndlessRecyclerView at the end of a NestedScrollView. EndlessRecyclerView means: when user scrolls to the bottom of the recyclerView it loads more data. This is already implemented and working elsewhere but when I put the recyclerView inside the NestedScrollView the OnScrollListener events doesn't fire.

XML design:

<NestedScrollView>

     <Other views/>

     <EndlessRecyclerView/>

</NestedScrollView >

Code:

recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            // This is never fired! Here is where I implement the logic of EndlessRecyclerView
        }
    });

How do I get scroll event for above case?

I know that is not good to have two scrollable views inside each other. But, how do I have the above case without having two scrollable views?

I already followed this link but it doesn't work: scroll event for recyclerview inside scrollview android

Lubbi answered 6/10, 2016 at 11:28 Comment(0)
F
110

To achieve endless scrolling for recycler view which is under NestedScrollView, you can use "NestedScrollView.OnScrollChangeListener"

nestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
            if(v.getChildAt(v.getChildCount() - 1) != null) {
                if ((scrollY >= (v.getChildAt(v.getChildCount() - 1).getMeasuredHeight() - v.getMeasuredHeight())) &&
                        scrollY > oldScrollY) {
                        //code to fetch more data for endless scrolling
                }
            }
        });

Here v.getChildCount() -1 should give you the recycler view for which you be implementing endless scrolling.

Also scrollY > oldScrollY confirms that the page is being scrolled down.

Reference: NestedScrollView.OnScrollChangeListener

Fructiferous answered 21/12, 2016 at 12:14 Comment(7)
Awesome Man I spend whole day seriously to resolve it you make it in two lines. Great this one... But now how can I get the visible items and all so I can fetch new records on server?Stuffy
@RahulVats In the above code when the if condition is met, it means that user has scrolled down completely and last item is visible. Let's say you have 100 items and initially 20 items are loaded. If the above condition is met, you can download the next set of data (ex: 21-40) from your server. Anyway, you can refer this link for your actual query: #40726938Fructiferous
Call requires API level 23 I think if the View above RecyclerView is not too complicated, we should implement it as different item type of RecyclerView and remove NestedScrollView, it can keep recycling technique also.Botany
@ThinkTwiceCodeOnce It doesn't need API level 23. It supports from API 14. You can read more about it here - developer.android.com/reference/android/support/v4/widget/…Fructiferous
@ThinkTwiceCodeOnce When you set this listener, you should use NestedScrollView.OnScrollChangeListener(), not View.OnScrollChangeListener().Shedd
not working i see on scroll api calling twiceWelcome
Same, api called twice, any solution you find?Jordain
O
4
nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener()
{
    @Override
    public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
    {
       if (v.getChildAt(v.getChildCount() - 1) != null)
       {
          if (scrollY > oldScrollY)
          {
             if (scrollY >= (v.getChildAt(v.getChildCount() - 1).getMeasuredHeight() - v.getMeasuredHeight()))
             {
                //code to fetch more data for endless scrolling
             }
          }
       }
    }
 });
Outhe answered 4/11, 2020 at 12:39 Comment(0)
C
3

I had a similar issue, although it was a little different. In my case I had a recycleview within a fragment while the NestedScrollView was in the content_main xml (part of the activity).

I wrapped my recycleview that was within the fragment with SwipeRefreshLayout

This is the code of my fragment:

    <?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/swipe_dummy"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/top_series_recycle_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

The only thing is left to do is to disable the SwipeRefreshLayout from the code

mSwipeLayout.isEnabled = false

If you won't do that, when you swipe down it will show endless refresh icon. I wanted to share this solution in case someone will need this functionality or have this issue as well

After you will wrap the recycleview with a SwipeRefreshLayout, you will see addOnScrollListener of the recycleview will be called as usual

Chainman answered 11/4, 2019 at 20:55 Comment(0)
K
0
nestedScrollView.setOnScrollChangeListener { v: NestedScrollView?, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int ->

        val view = nestedScrollView.getChildAt(nestedScrollView.childCount - 1)
        Timber.d("Count==============${nestedScrollView.childCount}")

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

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


    }
Kenya answered 12/5, 2021 at 7:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.