RecyclerView 解析(三)
2016-06-06 21:56
501 查看
一、前言
RecyclerView 解析第三篇。
如果你对RecyclerView 没有一个基础的认识,那建议你去读前两篇博客。
第一篇博客主要是讲,RecyclerView 基本用法。RecyclerView (解析一)
第二篇博客将RecyclerView Item之间的拖动,以及滑动删除动画相关做了大概介绍。RecyclerView (解析二)
本篇博客想向各位介绍RecyclerView 相关库。
主要是常用的下拉刷新,上拉加载更多,及其原理。大家可以根据原理自己实现下拉刷新
,及上拉加载更多。当然还会介绍其他的一些库。不过相对的篇幅会小一些。
二、XRecyclerView 实现下拉刷新,上拉加载更多。
首先来看看效果:
基本用法:
1、 添加库 compile ‘com.jcodecraeer:xrecyclerview:1.2.7’
2、布局:
利用com.jcodecraeer.xrecyclerview.XRecyclerView 替换 RecyclerView 。
3、代码
View view = LayoutInflater.from(this).inflate(R.layout.ultimate_header,mRecyclerView,false);
mRecyclerView.addHeaderView(view);
利用mRecyclerView.addHeaderView(view);添加HeadView。集成者可以添加多个HeadView。
mCommonAdapter 为自定义Adapter。与本文无关,读者可以自己参照RecyclerView 第一篇博客自己实现。
mRecyclerView.setPullRefreshEnabled(true);设置刷新可用。XRecyclerView 这个库默认即可刷新。不需要刷新时可以设置为False。
mRecyclerView.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader);
mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallGridPulse);
设置下拉刷新及上拉加载更多不同的Style。这里XRecyclerView 默认提供了许多的Style。即库内置了许多不同的图片,用于下拉及上拉时显示。
mRecyclerView.setArrowImageView();
集成者可以通过这个方法设置自己想要的下拉刷新图片。
mRecyclerView.setLoadingListener()。下拉刷新以及上拉加载更多回调。注意该回调是在主线程中。所以想要做耗时操作需要在子线程中。
刷新成功后调用mRecyclerView.refreshComplete();通知已经成功。
上拉加载成功后调用mRecyclerView.loadMoreComplete();通知已经成功。
setEmptyView(); RecyclerView 没有像ListView一样提供setEmptyView()这样的方法。这个库为我们提供了这个方法。
4、这个库的用法相对简单,我们可以其实现原理。
XRecyclerView extends RecyclerView 。
XRecyclerView 继承自RecyclerView 。
private ArrayList mHeaderViews = new ArrayList<>();
private ArrayList mFootViews = new ArrayList<>();
其内部维护了两个HeadView FootView集合。
其在构造方法中调用了init()方法。ArrowRefreshHeader 为自定义的下拉刷新的View。LoadingMoreFooter 为自定义上拉加载View。可以看到在初始化时,分别将已经实现好的下拉刷新View已经上拉加载View添加到集合中。
下面来看addHeaderView()方法。
可以看到addHeaderView()方法中将HeadView,和ArrowRefreshHeader 一样加入到mHeaderViews 集合中,并且ArrowRefreshHeader 永远是在第一位。
private class WrapAdapter extends RecyclerView.Adapter {
“`
Adapter中有这样几个方法值得我们注意。
就可以把整个过程弄明白了。通过getItemViewType()方法根据position 判断是HeadView还是FootView或者是正常View。在onCreateViewHolder()方法根据Type,如果是第一个View,也就是我们下拉刷新看到的View。
或者是我们通过addHeadView()方法添加进去的View,那就从mHeaderViews集合中取值组装ViewHolder。
如果是FootView就从mFootViews取值,组装ViewHolder。
如果都不是那便调用我们在外面自定义的adapter的onCreateViewHolder()。
这里我就搞明白了,为什么它可以添加多个HeadView。原理就是内部维护了集合,无论添加多少HeadView,在onCreateViewHolder()生成对应的ViewHolder就行了。并且注意onBindViewHolder(),getItemCount()考虑到数量的情况就好了
其他的方法均比较好理解。这里值得注意的方法就是onAttachedToRecyclerView()方法。
就是通过onAttachedToRecyclerView(),判断即使是GridLayoutManager,设置有好几列的情况,如何能让HeadView以及FootView依然是自己占用一行。就是在这个方法中判断如果是
GridLayoutManager,返回当前这个View的SpanSize为1就好了。
OK,大致的情况就介绍好了。原理依然是利用getItemViewType()与ListView一样。
哦,忘记了项目地址:https://github.com/jianghejie/XRecyclerView
三、其他的库:
UltimateRecyclerView Github上面Star非常的多。
项目地址:https://github.com/cymcsg/UltimateRecyclerView
这个库本来我也是用了一下,实现了很多功能。不足之处就是作者给的Demo,写的是在天马行空,看一会就失去兴致了。使用起来也比较繁琐。其内部是对RecyclerView 进行了再次包装,
UltimateRecyclerView 是一个FrameLayout。其内部是拥有一个RecyclerView 的对象。以后有时间可能会再研究研究。
还有:
PullLoadMoreRecyclerView https://github.com/WuXiaolong/PullLoadMoreRecyclerView
HeaderAndFooterRecyclerView https://github.com/cundong/HeaderAndFooterRecyclerView
IRecyclerView https://github.com/Aspsine/IRecyclerView
等等
RecyclerView 解析第三篇。
如果你对RecyclerView 没有一个基础的认识,那建议你去读前两篇博客。
第一篇博客主要是讲,RecyclerView 基本用法。RecyclerView (解析一)
第二篇博客将RecyclerView Item之间的拖动,以及滑动删除动画相关做了大概介绍。RecyclerView (解析二)
本篇博客想向各位介绍RecyclerView 相关库。
主要是常用的下拉刷新,上拉加载更多,及其原理。大家可以根据原理自己实现下拉刷新
,及上拉加载更多。当然还会介绍其他的一些库。不过相对的篇幅会小一些。
二、XRecyclerView 实现下拉刷新,上拉加载更多。
首先来看看效果:
基本用法:
1、 添加库 compile ‘com.jcodecraeer:xrecyclerview:1.2.7’
2、布局:
<com.jcodecraeer.xrecyclerview.XRecyclerView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/recycler_view" />
利用com.jcodecraeer.xrecyclerview.XRecyclerView 替换 RecyclerView 。
3、代码
package recyclerdemo.li.com.recyclerdemo.refresh; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import com.jcodecraeer.xrecyclerview.ProgressStyle; import com.jcodecraeer.xrecyclerview.XRecyclerView; import java.util.ArrayList; import java.util.List; import recyclerdemo.li.com.recyclerdemo.R; import recyclerdemo.li.com.recyclerdemo.common.CommonAdapter; import recyclerdemo.li.com.recyclerdemo.common.ViewHolder; public class RefreshActivity extends Activity { private List<String> mData; private Handler mHandler; private XRecyclerView mRecyclerView; private CommonAdapter mCommonAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.refresh_activity); mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); int i = msg.what; switch (i){ case 1: mData.add(0,"refresh"); mRecyclerView.refreshComplete(); mCommonAdapter.notifyDataSetChanged(); break; case 2: mData.add("loadMore"); mRecyclerView.loadMoreComplete(); mCommonAdapter.notifyDataSetChanged(); break; default: break; } } }; initData(); initView(); } public void initView(){ mRecyclerView = (XRecyclerView)findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); View view = LayoutInflater.from(this).inflate(R.layout.ultimate_header,mRecyclerView,false); mRecyclerView.addHeaderView(view); mCommonAdapter = new CommonAdapter(this,R.layout.recycler_item,mData) { @Override public void convert(RecyclerView.ViewHolder holder, Object o) { ViewHolder viewHolder = (ViewHolder)holder; viewHolder.setTextView(R.id.text,(String)o); } }; mRecyclerView.setAdapter(mCommonAdapter); mRecyclerView.setPullRefreshEnabled(true); //设置刷新Style mRecyclerView.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader); //设置上拉加载更多Style // mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallGridPulse); mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() { @Override public void onRefresh() { refreshData(); } @Override public void onLoadMore() { loadData(); } }); } private void initData(){ if(mData == null){ mData = new ArrayList<String>(); } for(int i='A';i<='z';i++){ mData.add(""+(char)i); } } private void refreshData(){ new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(2000); Message msg = Message.obtain(); msg.what = 1; mHandler.sendMessage(msg); }catch (Exception e){ } } }).start(); } private void loadData(){ new Thread(new Runnable() { @Override public void run() { try{ Thread.sleep(2000); Message msg = Message.obtain(); msg.what = 2; mHandler.sendMessage(msg); }catch (Exception e){ } } }).start(); } }
View view = LayoutInflater.from(this).inflate(R.layout.ultimate_header,mRecyclerView,false);
mRecyclerView.addHeaderView(view);
利用mRecyclerView.addHeaderView(view);添加HeadView。集成者可以添加多个HeadView。
mCommonAdapter 为自定义Adapter。与本文无关,读者可以自己参照RecyclerView 第一篇博客自己实现。
mRecyclerView.setPullRefreshEnabled(true);设置刷新可用。XRecyclerView 这个库默认即可刷新。不需要刷新时可以设置为False。
mRecyclerView.setRefreshProgressStyle(ProgressStyle.LineSpinFadeLoader);
mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallGridPulse);
设置下拉刷新及上拉加载更多不同的Style。这里XRecyclerView 默认提供了许多的Style。即库内置了许多不同的图片,用于下拉及上拉时显示。
mRecyclerView.setArrowImageView();
集成者可以通过这个方法设置自己想要的下拉刷新图片。
mRecyclerView.setLoadingListener()。下拉刷新以及上拉加载更多回调。注意该回调是在主线程中。所以想要做耗时操作需要在子线程中。
刷新成功后调用mRecyclerView.refreshComplete();通知已经成功。
上拉加载成功后调用mRecyclerView.loadMoreComplete();通知已经成功。
setEmptyView(); RecyclerView 没有像ListView一样提供setEmptyView()这样的方法。这个库为我们提供了这个方法。
4、这个库的用法相对简单,我们可以其实现原理。
XRecyclerView extends RecyclerView 。
XRecyclerView 继承自RecyclerView 。
private ArrayList mHeaderViews = new ArrayList<>();
private ArrayList mFootViews = new ArrayList<>();
其内部维护了两个HeadView FootView集合。
private void init(Context context) { mContext = context; if (pullRefreshEnabled) { ArrowRefreshHeader refreshHeader = new ArrowRefreshHeader(mContext); mHeaderViews.add(0, refreshHeader); mRefreshHeader = refreshHeader; mRefreshHeader.setProgressStyle(mRefreshProgressStyle); } LoadingMoreFooter footView = new LoadingMoreFooter(mContext); footView.setProgressStyle(mLoadingMoreProgressStyle); addFootView(footView); mFootViews.get(0).setVisibility(GONE); }
其在构造方法中调用了init()方法。ArrowRefreshHeader 为自定义的下拉刷新的View。LoadingMoreFooter 为自定义上拉加载View。可以看到在初始化时,分别将已经实现好的下拉刷新View已经上拉加载View添加到集合中。
下面来看addHeaderView()方法。
public void addHeaderView(View view) { if (pullRefreshEnabled && !(mHeaderViews.get(0) instanceof ArrowRefreshHeader)) { ArrowRefreshHeader refreshHeader = new ArrowRefreshHeader(mContext); mHeaderViews.add(0, refreshHeader); mRefreshHeader = refreshHeader; mRefreshHeader.setProgressStyle(mRefreshProgressStyle); } mHeaderViews.add(view); sHeaderTypes.add(HEADER_INIT_INDEX + mHeaderViews.size()); }
可以看到addHeaderView()方法中将HeadView,和ArrowRefreshHeader 一样加入到mHeaderViews 集合中,并且ArrowRefreshHeader 永远是在第一位。
public void addFootView(final View view) { mFootViews.clear(); mFootViews.add(view); } `` 调用addFootView()方法 ,将我们自定义的View加入到mFootViews中。可以看到mFootViews中永远只有一个Item。表示FootView只能为一个。所以如果我们调用了addFootView()方法,我们自定义的FootView将会替换系统在init()方法中加入的FootView。 下面我们一起看Adapter:
private class WrapAdapter extends RecyclerView.Adapter {
private RecyclerView.Adapter adapter; private ArrayList<View> mHeaderViews; private ArrayList<View> mFootViews; private int headerPosition = 1; public WrapAdapter(ArrayList<View> headerViews, ArrayList<View> footViews, RecyclerView.Adapter adapter) { this.adapter = adapter; this.mHeaderViews = headerViews; this.mFootViews = footViews; } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if (manager instanceof GridLayoutManager) { final GridLayoutManager gridManager = ((GridLayoutManager) manager); gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return (isHeader(position) || isFooter(position)) ? gridManager.getSpanCount() : 1; } }); } } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams && (isHeader(holder.getLayoutPosition()) || isFooter(holder.getLayoutPosition()))) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } public boolean isHeader(int position) { return position >= 0 && position < mHeaderViews.size(); } public boolean isContentHeader(int position) { return position >= 1 && position < mHeaderViews.size(); } public boolean isFooter(int position) { return position < getItemCount() && position >= getItemCount() - mFootViews.size(); } public boolean isRefreshHeader(int position) { return position == 0; } public int getHeadersCount() { return mHeaderViews.size(); } public int getFootersCount() { return mFootViews.size(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_REFRESH_HEADER) { mCurrentPosition++; return new SimpleViewHolder(mHeaderViews.get(0)); } else if (isContentHeader(mCurrentPosition)) { if (viewType == sHeaderTypes.get(mCurrentPosition - 1)) { mCurrentPosition++; return new SimpleViewHolder(mHeaderViews.get(headerPosition++)); } } else if (viewType == TYPE_FOOTER) { return new SimpleViewHolder(mFootViews.get(0)); } return adapter.onCreateViewHolder(parent, viewType); } private int mCurrentPosition; @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isHeader(position)) { return; } int adjPosition = position - getHeadersCount(); int adapterCount; if (adapter != null) { adapterCount = adapter.getItemCount(); if (adjPosition < adapterCount) { adapter.onBindViewHolder(holder, adjPosition); return; } } } @Override public int getItemCount() { if (adapter != null) { return getHeadersCount() + getFootersCount() + adapter.getItemCount(); } else { return getHeadersCount() + getFootersCount(); } } @Override public int getItemViewType(int position) { if (isRefreshHeader(position)) { return TYPE_REFRESH_HEADER; } if (isHeader(position)) { position = position - 1; return sHeaderTypes.get(position); } if (isFooter(position)) { return TYPE_FOOTER; } int adjPosition = position - getHeadersCount(); int adapterCount; if (adapter != null) { adapterCount = adapter.getItemCount(); if (adjPosition < adapterCount) { return adapter.getItemViewType(adjPosition); } } return TYPE_NORMAL; } @Override public long getItemId(int position) { if (adapter != null && position >= getHeadersCount()) { int adjPosition = position - getHeadersCount(); int adapterCount = adapter.getItemCount(); if (adjPosition < adapterCount) { return adapter.getItemId(adjPosition); } } return -1; } @Override public void unregisterAdapterDataObserver(AdapterDataObserver observer) { if (adapter != null) { adapter.unregisterAdapterDataObserver(observer); } } @Override public void registerAdapterDataObserver(AdapterDataObserver observer) { if (adapter != null) { adapter.registerAdapterDataObserver(observer); } } private class SimpleViewHolder extends RecyclerView.ViewHolder { public SimpleViewHolder(View itemView) { super(itemView); } } }
“`
Adapter中有这样几个方法值得我们注意。
就可以把整个过程弄明白了。通过getItemViewType()方法根据position 判断是HeadView还是FootView或者是正常View。在onCreateViewHolder()方法根据Type,如果是第一个View,也就是我们下拉刷新看到的View。
或者是我们通过addHeadView()方法添加进去的View,那就从mHeaderViews集合中取值组装ViewHolder。
如果是FootView就从mFootViews取值,组装ViewHolder。
如果都不是那便调用我们在外面自定义的adapter的onCreateViewHolder()。
这里我就搞明白了,为什么它可以添加多个HeadView。原理就是内部维护了集合,无论添加多少HeadView,在onCreateViewHolder()生成对应的ViewHolder就行了。并且注意onBindViewHolder(),getItemCount()考虑到数量的情况就好了
其他的方法均比较好理解。这里值得注意的方法就是onAttachedToRecyclerView()方法。
就是通过onAttachedToRecyclerView(),判断即使是GridLayoutManager,设置有好几列的情况,如何能让HeadView以及FootView依然是自己占用一行。就是在这个方法中判断如果是
GridLayoutManager,返回当前这个View的SpanSize为1就好了。
OK,大致的情况就介绍好了。原理依然是利用getItemViewType()与ListView一样。
哦,忘记了项目地址:https://github.com/jianghejie/XRecyclerView
三、其他的库:
UltimateRecyclerView Github上面Star非常的多。
项目地址:https://github.com/cymcsg/UltimateRecyclerView
这个库本来我也是用了一下,实现了很多功能。不足之处就是作者给的Demo,写的是在天马行空,看一会就失去兴致了。使用起来也比较繁琐。其内部是对RecyclerView 进行了再次包装,
UltimateRecyclerView 是一个FrameLayout。其内部是拥有一个RecyclerView 的对象。以后有时间可能会再研究研究。
还有:
PullLoadMoreRecyclerView https://github.com/WuXiaolong/PullLoadMoreRecyclerView
HeaderAndFooterRecyclerView https://github.com/cundong/HeaderAndFooterRecyclerView
IRecyclerView https://github.com/Aspsine/IRecyclerView
等等
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories