我想把ListView改为RecyclerView。我想在RecyclerView中使用OnScrollListener的onScroll来确定用户是否滚动到列表的末尾。

我如何知道用户是否滚动到列表的末尾以便我可以从REST服务获取新数据?


当前回答

虽然接受的答案工作得很好,但下面的解决方案使用addOnScrollListener,因为setOnScrollListener已弃用,并减少了变量的数量,以及if条件。

final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
feedsRecyclerView.setLayoutManager(layoutManager);

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

        if (dy > 0) {   
            if ((layoutManager.getChildCount() + layoutManager.findFirstVisibleItemPosition()) >= layoutManager.getItemCount()) {
                Log.d("TAG", "End of list");
                //loadMore();
            }
        }
    }
});

其他回答

检查的每一件事都有详细的解释: 使用RecyclerView从A到Z分页

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView,
                                     int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount = mLayoutManager.getChildCount();
        int totalItemCount = mLayoutManager.getItemCount();
        int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();

        if (!mIsLoading && !mIsLastPage) {
            if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
                    && firstVisibleItemPosition >= 0) {
                loadMoreItems();
            }
        }
    }
})

loadMoreItems ():

private void loadMoreItems() {
    mAdapter.removeLoading();
    //load data here from the server

    // in case of success
    mAdapter.addData(data);
    // if there might be more data
    mAdapter.addLoading();
}

在MyAdapter中:

private boolean mIsLoadingFooterAdded = false;

public void addLoading() {
    if (!mIsLoadingFooterAdded) {
        mIsLoadingFooterAdded = true;
        mLineItemList.add(new LineItem());
        notifyItemInserted(mLineItemList.size() - 1);
    }
}

public void removeLoading() {
    if (mIsLoadingFooterAdded) {
        mIsLoadingFooterAdded = false;
        int position = mLineItemList.size() - 1;
        LineItem item = mLineItemList.get(position);

        if (item != null) {
            mLineItemList.remove(position);
            notifyItemRemoved(position);
        }
    }
}

public void addData(List<YourDataClass> data) {

    for (int i = 0; i < data.size(); i++) {
        YourDataClass yourDataObject = data.get(i);
        mLineItemList.add(new LineItem(yourDataObject));
        notifyItemInserted(mLineItemList.size() - 1);
    }
}

我已经创建LoadMoreRecyclerView使用Abdulaziz Noor回答

LoadMoreRecyclerView

public class LoadMoreRecyclerView extends RecyclerView  {

    private boolean loading = true;
    int pastVisiblesItems, visibleItemCount, totalItemCount;
    //WrapperLinearLayout is for handling crash in RecyclerView
    private WrapperLinearLayout mLayoutManager;
    private Context mContext;
    private OnLoadMoreListener onLoadMoreListener;

    public LoadMoreRecyclerView(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    public LoadMoreRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        init();
    }

    private void init(){
        mLayoutManager = new WrapperLinearLayout(mContext,LinearLayoutManager.VERTICAL,false);
        this.setLayoutManager(mLayoutManager);
        this.setItemAnimator(new DefaultItemAnimator());
        this.setHasFixedSize(true);
    }

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

        if(dy > 0) //check for scroll down
        {
            visibleItemCount = mLayoutManager.getChildCount();
            totalItemCount = mLayoutManager.getItemCount();
            pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

            if (loading)
            {
                if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
                {
                    loading = false;
                    Log.v("...", "Call Load More !");
                    if(onLoadMoreListener != null){
                        onLoadMoreListener.onLoadMore();
                    }
                    //Do pagination.. i.e. fetch new data
                }
            }
        }
    }

    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
    }

    public void onLoadMoreCompleted(){
        loading = true;
    }

    public void setMoreLoading(boolean moreLoading){
        loading = moreLoading;
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }
}

WrapperLinearLayout

public class WrapperLinearLayout extends LinearLayoutManager
{
    public WrapperLinearLayout(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        try {
            super.onLayoutChildren(recycler, state);
        } catch (IndexOutOfBoundsException e) {
            Log.e("probe", "meet a IOOBE in RecyclerView");
        }
    }
}

//在xml中添加

<your.package.LoadMoreRecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</your.package.LoadMoreRecyclerView>

OnCreate或onViewCreated

mLoadMoreRecyclerView = (LoadMoreRecyclerView) view.findViewById(R.id.recycler_view);
mLoadMoreRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                callYourService(StartIndex);
            }
        });

callYourService

private void callYourService(){
    //callyour Service and get response in any List

    List<AnyModelClass> newDataFromServer = getDataFromServerService();
    //Enable Load More
    mLoadMoreRecyclerView.onLoadMoreCompleted();

    if(newDataFromServer != null && newDataFromServer.size() > 0){
            StartIndex += newDataFromServer.size();

            if (newDataFromServer.size() < Integer.valueOf(MAX_ROWS)) {
                    //StopLoading..
                   mLoadMoreRecyclerView.setMoreLoading(false);
            }
    }
    else{
            mLoadMoreRecyclerView.setMoreLoading(false);
            mAdapter.notifyDataSetChanged();
    }
}

正如约翰·T所建议的。只需使用下面的代码块,真的很简短,美观简单:D

public void loadMoreOnRecyclerView() {
    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(@NonNull @NotNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if (!recyclerView.canScrollVertically(1) && dy != 0) {
                //Load more items here
            }
        }
    });
}

你可以跟随我的回购来了解它的工作方式。

https://github.com/Nghien-Nghien/PokeAPI-Java/blob/0d8d69d348e068911b883f0ae7791d904cc75cb5/app/src/main/java/com/example/pokemonapi/MainActivity.java

关于应用程序的描述信息如下:https://github.com/skydoves/Pokedex#readme

@erdna请参考我下面的代码。也许它会对你有帮助。

     int firstVisibleItem, visibleItemCount, totalItemCount;
   recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

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

            visibleItemCount = layoutManager.getChildCount();
            totalItemCount = layoutManager.getItemCount();
            firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
            Log.e("firstVisibleItem", firstVisibleItem + "");
            Log.e("visibleItemCount", visibleItemCount + "");
            Log.e("totalItemCount", totalItemCount + "");

            if (page != total_page_index) {
                if (loading) {
                    if ((visibleItemCount + firstVisibleItem) >= totalItemCount) {
                        Log.e("page", String.valueOf(page));
                        page=page+1;
                        new GetSummary().execute(String.valueOf(page), "");
                        loading = false;
                    }
                }
            }

        }


    });

试试下面:

import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;

/**
 * Abstract Endless ScrollListener
 * 
 */
public abstract class EndlessScrollListener extends
        RecyclerView.OnScrollListener {
    // The minimum amount of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold = 10;
    // The current offset index of data you have loaded
    private int currentPage = 1;
    // True if we are still waiting for the last set of data to load.
    private boolean loading = true;
    // The total number of items in the data set after the last load
    private int previousTotal = 0;
    private int firstVisibleItem;
    private int visibleItemCount;
    private int totalItemCount;
    private LayoutManager layoutManager;

    public EndlessScrollListener(LayoutManager layoutManager) {
        validateLayoutManager(layoutManager);
        this.layoutManager = layoutManager;
    }

    public EndlessScrollListener(int visibleThreshold,
            LayoutManager layoutManager, int startPage) {
        validateLayoutManager(layoutManager);
        this.visibleThreshold = visibleThreshold;
        this.layoutManager = layoutManager;
        this.currentPage = startPage;
    }

    private void validateLayoutManager(LayoutManager layoutManager)
            throws IllegalArgumentException {
        if (null == layoutManager
                || !(layoutManager instanceof GridLayoutManager)
                || !(layoutManager instanceof LinearLayoutManager)) {
            throw new IllegalArgumentException(
                    "LayoutManager must be of type GridLayoutManager or LinearLayoutManager.");
        }
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = layoutManager.getItemCount();
        if (layoutManager instanceof GridLayoutManager) {
            firstVisibleItem = ((GridLayoutManager) layoutManager)
                    .findFirstVisibleItemPosition();
        } else if (layoutManager instanceof LinearLayoutManager) {
            firstVisibleItem = ((LinearLayoutManager) layoutManager)
                    .findFirstVisibleItemPosition();
        }
        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading
                && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
            // End has been reached do something
            currentPage++;
            onLoadMore(currentPage);
            loading = true;
        }
    }

    // Defines the process for actually loading more data based on page
    public abstract void onLoadMore(int page);

}