RecyclerView 增加下拉刷新,上拉加载更多功能分析

业务需要RecyclerView增加上拉刷新,下拉加载更多功能,于是写了个Demo,看看运行效果。
这里写图片描述

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

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

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
    </android.support.v4.widget.SwipeRefreshLayout>

</LinearLayout>

TestActivity:

package comm.example.hongentao.recyclerviewloadmore;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by hongentao on 16/3/10.
 */
public class TestActivity extends Activity {
    private RecyclerView mRecyclerView;
    private TestAdapter mTestAdapter;
    private LinearLayoutManager mLayoutManager;
    private Handler myHandler;
    private SwipeRefreshLayout mSwipRefreshLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initView();
        init();
    }


    private void initView() {
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mSwipRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swiprefreshlayout);
    }

    private void init() {
        myHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        };
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mTestAdapter = new TestAdapter(this, mRecyclerView);
        final List<String> mList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            mList.add("haha");
        }
        mTestAdapter.mList.clear();
        mTestAdapter.mList.addAll(mList);
        mTestAdapter.setLoadMore(true);
        mTestAdapter.addOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void loadMore() {
                mTestAdapter.mList.add(null);
                mTestAdapter.notifyItemInserted(mTestAdapter.mList.size() - 1);
                myHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mTestAdapter.mList.remove(mTestAdapter.mList.size() - 1);
                        mTestAdapter.notifyItemRemoved(mTestAdapter.mList.size());
                        for (int i = 0; i < 30; i++) {
                            mTestAdapter.mList.add("haha");
                            mTestAdapter.notifyItemInserted(mTestAdapter.mList.size());
                        }
                        mTestAdapter.setLoaded();
                    }
                }, 2 * 1000);
            }
        });

        mSwipRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mTestAdapter.mList.clear();
                final List<String> mList = new ArrayList<>();
                for (int i = 0; i < 20; i++) {
                    mList.add("haha");
                }
                mTestAdapter.mList.addAll(mList);
                mTestAdapter.notifyDataSetChanged();
                myHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mSwipRefreshLayout.setRefreshing(false);
                    }
                }, 2 * 1000);
            }
        });
        mRecyclerView.setAdapter(mTestAdapter);
    }
}

TestAdapter:

package comm.example.hongentao.recyclerviewloadmore;

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by hongentao on 16/3/10.
 */
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyHolder> {
    private Context mContext;
    private OnLoadMoreListener mOnLoadMoreListener;
    public List<String> mList = new ArrayList<>();
    public static final int LOADMORE = 1;
    public static final int NORMAL = 2;
    private int visibleItemCount;
    private int totalItemCount;
    private int firstVisibleItem;
    private boolean loading = false;
    private boolean isLoadMore = true;

    public TestAdapter(Context context, RecyclerView recyclerView) {
        this.mContext = context;
        final LinearLayoutManager mLayoutManager;
        if (recyclerView != null && recyclerView.getLayoutManager() instanceof
                LinearLayoutManager) {
            mLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
            recyclerView.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);
                    // check for scroll down
                    if (isLoadMore) {
                        if (dy > 0) {
                            visibleItemCount = mLayoutManager.getChildCount();
                            totalItemCount = mLayoutManager.getItemCount();
                            firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
                            if (!loading) {
                                if (totalItemCount <= visibleItemCount + firstVisibleItem) {
                                    if (mOnLoadMoreListener != null) {
                                        mOnLoadMoreListener.loadMore();
                                    }
                                    loading = true;
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    /**
     * 设置下拉加载更多功能
     *
     * @param isLoadMore
     */
    public void setLoadMore(boolean isLoadMore) {
        this.isLoadMore = isLoadMore;
    }

    /**
     * reset loading status
     */
    public void setLoaded() {
        loading = false;
    }


    public void addOnLoadMoreListener(OnLoadMoreListener mLoadMoreListener) {
        this.mOnLoadMoreListener = mLoadMoreListener;
    }

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View mView = null;
        switch (viewType) {
            case LOADMORE:
                mView = LayoutInflater.from(mContext).inflate(R.layout.progressbar_item, null);
                break;
            case NORMAL:
                mView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
                break;
        }
        return new MyHolder(mView, viewType);
    }

    @Override
    public void onBindViewHolder(MyHolder holder, int position) {
        if (mList.get(position) == null) {
            holder.mProgressBar.setIndeterminate(true);
        } else {
            holder.mTextView.setText(mList.get(position));
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (mList.get(position) == null) {
            return LOADMORE;
        } else {
            return NORMAL;
        }
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public class MyHolder extends RecyclerView.ViewHolder {
        private TextView mTextView;
        private ProgressBar mProgressBar;

        public MyHolder(View itemView, int viewType) {
            super(itemView);
            init(itemView, viewType);
        }

        private void init(View view, int viewType) {
            switch (viewType) {
                case LOADMORE:
                    mProgressBar = (ProgressBar) view.findViewById(R.id.progressbar);
                    break;
                case NORMAL:
                    mTextView = (TextView) view.findViewById(R.id.textview);
                    break;
                default:
                    break;
            }
        }
    }
}

下拉刷新采用v4自带的SwipRefreshLayout,上拉加载更多在RecyclerView的适配器中做文章, 通过viewType设置不同的item布局。巧妙的运用mList的源数据,如果mList.get(position) == null 就加载Loading布局, 反之就加载正常布局。 等到loading完成后,就remove掉loading布局。

recyclerView的onScrollListener监听是上拉加载更多的关键。
1:firstVisibleItem 当前可见的第一条数据item postion。
2:visibleItemCount当前可见屏幕上总的item条数。
3:totalItemCount总共的item count条数。

loadmore前提条件:
1:dy > 0
当RecyclerView Y轴上滑动距离大于0时才会触发,这样的话当RecyclerView item数较少无法充满RecyclerView时,触摸RecyclerView不会滚动,进而不会触发LoadMore功能。

2:(totalItemCount <= visibleItemCount + firstVisibleItem)
当前可见的item总数 + 可见范围内第一个item的位置 >= item的总数,表明item已经滑动到最后了。

onLoadMoreListener:

package comm.example.hongentao.recyclerviewloadmore;

/**
 * Created by hongentao on 16/3/10.
 */
public interface OnLoadMoreListener {
    void loadMore();
}

list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="50dp"/>
</LinearLayout>

progressbar_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

    <ProgressBar
        android:id="@+id/progressbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

github下载地址:
感觉对你有帮助的话,跪求star!!!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值