RecyclerView下拉刷新上拉加载更多

Posted on 2017-05-07 11:50  xl_phoenix  阅读(689)  评论(0编辑  收藏  举报

现在Android里都建议用RecyclerView代替ListView和GridView,所以下拉刷新和上拉加载更多也需要实现。下拉刷新可以用SwipeRefreshLayout 包裹RecyclerView实现下拉刷新,二是滑倒底部的时候自动加载实现加载更多。

需要注意的是两点:

  • 下拉刷新是通过实现SwipeRefreshLayout.OnRefreshListener接口来实现的,也就是说下拉刷新具有了通用性,不只是RecyclerView;
  • 加载更多要通过LinearLayoutManager来获取RecyclerView是否滑动到底部来实现。

下拉刷新

xml布局文件

<android.support.v4.widget.SwipeRefreshLayout 
    android:id="@+id/swipe_refresh"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/swipe_target"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none" />

</android.support.v4.widget.SwipeRefreshLayout>

Activity代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
    swipeRefreshLayout.setColorSchemeResources(
            R.color.google_blue,
            R.color.google_green,
            R.color.google_red,
            R.color.google_yellow
    );
    recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(linearLayoutManager);
    setData();
    RefreshAdapter refreshAdapter = new RefreshAdapter(mList, this);
    recyclerView.setAdapter(refreshAdapter);
    swipeRefreshLayout.setOnRefreshListener(this);
}


private void setData() {
    mList = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
        mList.add("第" + i + "个");
    }
}

@Override
public void onRefresh() {
    Observable
            .timer(2, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
            .map(new Func1<Long, Object>() {
                @Override
                public Object call(Long aLong) {
                    fetchingNewData();
                    swipeRefreshLayout.setRefreshing(false);
                    refreshAdapter.notifyDataSetChanged();
                    Toast.makeText(MainActivity.this, "Refresh Finished!", Toast.LENGTH_SHORT).show();
                    return null;
                }
            }).subscribe();
}

private void fetchingNewData() {
    mList.add(0, "下拉刷新出来的数据");
}

上拉加载更多

RecyclerView有一个方法addOnScrollListener,我们只要传入一个 RecyclerView.OnScrollListener就可以实现加载更多了,但是为了充分保证 RecyclerView 的灵活性,Android 本身是没有对这个滑动接口做处理的,需要我们自定义个加载更多的接口去实现它,然后才能真正实现加载更多。实现起来也很简单,我们只要重写 onScrolled 方法即可。

我们只需要封装好一个加载更多的接口实现类,然后传参数进去

public abstract class EndlessRecyclerOnScrollListener extends
        RecyclerView.OnScrollListener {

    private int previousTotal = 0;
    private boolean loading = true;
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int currentPage = 1;

    private LinearLayoutManager mLinearLayoutManager;

    public EndlessRecyclerOnScrollListener(
            LinearLayoutManager linearLayoutManager) {
        this.mLinearLayoutManager = linearLayoutManager;
    }

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

        visibleItemCount = recyclerView.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

        if (loading) {
            if (totalItemCount > previousTotal) {
                loading = false;
                previousTotal = totalItemCount;
            }
        }
        if (!loading
                && (totalItemCount - visibleItemCount) <= firstVisibleItem) {
            currentPage++;
            onLoadMore(currentPage);
            loading = true;
        }
    }

    public abstract void onLoadMore(int currentPage);
}

实现加载更多的逻辑

recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) {
    @Override
    public void onLoadMore(int currentPage) {
        simulateLoadMoreData();
    }
});

private void simulateLoadMoreData() {
    Observable
            .timer(2, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
            .map(new Func1<Long, Object>() {
                @Override
                public Object call(Long aLong) {
                    loadMoreData();
                    stringAdapter.notifyDataSetChanged();
                    Toast.makeText(MainActivity.this, "Load Finished!", Toast.LENGTH_SHORT).show();
                    return null;
                }
            }).subscribe();
}

private void loadMoreData() {
    List<String> moreList = new ArrayList<>();
    for (int i = 10; i < 13; i++) {
        moreList.add("加载更多的数据");
    }
    mList.addAll(moreList);
}

当然,如果你想要一个加载更多的 ProgressBar 展示的话,可以给 RecyclerView 添加一个 Footer ,用来展示加载更多的过程。

参考资料:给RecyclerView最纯粹的下拉刷新和上拉加载更多
RecyclerView 下拉刷新和上拉加载
Android 实现自己的RecyclerView加载更多

Copyright © 2024 xl_phoenix
Powered by .NET 9.0 on Kubernetes