1

我正在尝试使用 recyclerview 实现无限滚动,并且效果很好。但是,我注意到当内容大小小于屏幕高度时,永远不会调用 onScrolled。我想在向下滚动时加载更多内容,但我无法检测到向下滚动手势,因为从未调用过 onScrolled,因此我无法获得 dy 值。我想知道:

1)在这种情况下如何获得滚动方向 2)这种情况的最佳做法是什么?每次服务电话我都会收到一定数量的物品。如果返回的项目数没有填满屏幕会发生什么?

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
        {
            int lastVisibleItemPosition, visibleItemCount, totalItemCount;

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy)
            {
                super.onScrolled(recyclerView, dx, dy);

                if(dy>0)
                {
                    visibleItemCount = recyclerLayoutManager.getChildCount();
                    totalItemCount = recyclerLayoutManager.getItemCount();
                    lastVisibleItemPosition = recyclerLayoutManager.findLastVisibleItemPosition();


                    if (lastVisibleItemPosition >= totalItemCount)
                    {

                        if (!loading && dy>0 && moreToload)
                        {
                            loadMore();
                        }                      
                    }
                }

            }
});

谢谢!

4

4 回答 4

1

onScrolled如果在布局计算后可见项目范围发生变化,也会调用回调。请在此处查看链接。

这意味着它总是在完成将项目加载到回收站视图后调用一次

 @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    visibleItemCount = recyclerLayoutManager.getChildCount();
    totalItemCount = recyclerLayoutManager.getItemCount();
    lastVisibleItemPosition = recyclerLayoutManager.findLastVisibleItemPosition();

    if ((totalItemCount == visibleItemCount) || //This mean you still have space in your screen
        (dy > 0 && !loading && lastVisibleItemPosition >= totalItemCount)) {
        // Call load more here
    }
}

如果服务器没有返回任何项目,recyclerView 将不会更新,并且默认情况下onScroll不会再次调用方法,直到您到达 recyclerView 的末尾。

于 2017-09-17T21:55:05.297 回答
0
  1. 创建一个 LinearLayoutManager 的子类,它可以让您监听 onLayoutCompleted() 事件:
/**
 * This class calls [mCallback] (instance of [OnLayoutCompleteCallback]) when all layout
 * calculations are complete, e.g. following a call to
 * [RecyclerView.Adapter.notifyDataSetChanged()] (or related methods).
 *
 * In a paginated listing, we will decide if load more needs to be called in the said callback.
 */
class NotifyingLinearLayoutManager(context: Context) : LinearLayoutManager(context, VERTICAL, false) {
    var mCallback: OnLayoutCompleteCallback? = null

    override fun onLayoutCompleted(state: RecyclerView.State?) {
        super.onLayoutCompleted(state)
        mCallback?.onLayoutComplete()
    }

    fun isLastItemCompletelyVisible() = findLastCompletelyVisibleItemPosition() == itemCount - 1

    interface OnLayoutCompleteCallback {
        fun onLayoutComplete()
    }
}
  1. 在您的侦听器中,您可以决定是否需要调用加载更多内容:
mLayoutManager.mCallback = object : NotifyingLinearLayoutManager.OnLayoutCompleteCallback {
    override fun onLayoutComplete() {
        // here we know that the view has been updated.
        loadMoreIfNeeded()
    }
}
  1. 我的loadMoreIfNeeded()样子如下:
private fun loadMoreIfNeeded() {
    if (isAppropriateToLoadMoreItems() && !mLoadMoreRequestFired.getAndSet(true)) {
        mListener.onLoadMore()
    }
}

private fun isAppropriateToLoadMoreItems() =
        mLoadMoreEnabled && itemCount > 1 && mLayoutManager.isLastItemCompletelyVisible()

  1. 这些是上一步中使用的以下字段:
private var mLoadMoreRequestFired = AtomicBoolean(false)
// makes sure that we fire a single load more call at a time

private var mLoadMoreEnabled = false
// this flag is used by the footer (containing the ProgressBar) to show or hide it.
于 2019-09-06T10:36:44.587 回答
0

您可以尝试相同的方法,但需要RecyclerView.LayoutManager自定义和处理过度滚动

@Override
public int scrollVerticallyBy ( int dx, RecyclerView.Recycler recycler, 
RecyclerView.State state ) {
   int scrollRange = super.scrollVerticallyBy(dx, recycler, state);
   int overscroll = dx - scrollRange;
   if (overscroll > 0) {
    // bottom overscroll
   } else if (overscroll < 0) {
    // top overscroll
    }
   return scrollRange;
}
于 2017-08-11T13:01:09.737 回答
-1

只需删除if(dy > 0)您的代码上的。

最后的片段

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener()
    {
        int lastVisibleItemPosition, visibleItemCount, totalItemCount;

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy)
        {
            super.onScrolled(recyclerView, dx, dy);


            visibleItemCount = recyclerLayoutManager.getChildCount();
            totalItemCount = recyclerLayoutManager.getItemCount();
            lastVisibleItemPosition = recyclerLayoutManager.findLastVisibleItemPosition();


             if (lastVisibleItemPosition >= totalItemCount)
                {

                    if (!loading && dy>0 && moreToload)
                    {
                        loadMore();
                    }                      
                }
        }

});

于 2018-08-07T09:50:10.530 回答