在NestedScrollView中使用RecyclerView滚动监听器

44

我在一个NestedScrollView的末尾有一个EndlessRecyclerView。其中EndlessRecyclerView表示:当用户滚动到recyclerView的底部时,它会加载更多数据。这已经在其他地方实现并正常工作,但是当我将recyclerView放在NestedScrollView中时,OnScrollListener事件不会触发。

XML设计:

<NestedScrollView>

     <Other views/>

     <EndlessRecyclerView/>

</NestedScrollView >

代码:

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
        }
    });

如何获得上述情况的滚动事件?

我知道在两个可滚动视图内部不是一个好主意。但是,如果不使用两个可滚动视图,如何实现上述情况?

我已经按照此链接操作,但它不起作用:scroll event for recyclerview inside scrollview android

4个回答

110

要实现嵌套在NestedScrollView下的RecyclerView无限滚动,可以使用"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
                }
            }
        });

这里 v.getChildCount() -1 应该为你提供了实现无限滚动的 Recycler View。

同时,scrollY > oldScrollY 表示页面正在向下滚动。

参考文献:NestedScrollView.OnScrollChangeListener


太棒了,我花了一整天的时间认真解决它,而你只用了两行代码就搞定了。太厉害了!但是现在我该如何获取可见项和所有内容,以便从服务器获取新记录呢? - Rahul Vats
在上面的代码中,当if条件满足时,这意味着用户已经完全向下滚动并且最后一个项目可见。假设您有100个项目,并且最初加载了20个项目。如果满足上述条件,则可以从服务器下载下一组数据(例如:21-40)。无论如何,您可以参考此链接以获取实际查询:https://dev59.com/8VkR5IYBdhLWcg3w3AsM?noredirect=1&lq=1 - Govind
惊人的。谢谢。 - Neuron
5
设置此监听器时,应使用NestedScrollView.OnScrollChangeListener()而不是View.OnScrollChangeListener()。 - Smiles
1
看起来不起作用,我发现在滚动时API被调用了两次。 - user13352267
显示剩余3条评论

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
             }
          }
       }
    }
 });

3
我遇到了一个类似的问题,尽管有些不同。我的情况是在活动的content_main xml中(作为一部分)放置了NestedScrollView,而在片段中放置了recycleview。
我使用SwipeRefreshLayout包裹了片段中的recycleview。
这是我的片段代码:
    <?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>

唯一要做的就是从代码中禁用SwipeRefreshLayout。
mSwipeLayout.isEnabled = false

如果您不这样做,当您向下滑动时,它会显示无尽的刷新图标。我想分享这个解决方案,以防有人需要此功能或遇到此问题。

在将recycleview包装在SwipeRefreshLayout中之后,您将看到recycleview的addOnScrollListener将像往常一样被调用。


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()
        }


    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接