前言
我们大家都知道ListVIEw具有添加头部和添加底部的方法,但是RecyclerVIEw并没有这样子的方法。所以RecyclerVIEw是不能添加底部和头部的,但是能不能仿造ListVIEw来实现RecyclerVIEw添加头部和底部呢?答案当然是可行的。本文就来给大家介绍了关于AndroID封装RecyclerVIEw添加头部和底部的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
首先看下实现的效果:
代码如下:
public class WrapMyRecyclerVIEw extends RecyclerVIEw { private Adapter mAdapter; private ArrayList<VIEw> mheaderVIEwInfos = new ArrayList<>();//保存headerVIEw private ArrayList<VIEw> mFooterVIEwInfos = new ArrayList<>();//保存footerVIEw public WrapMyRecyclerVIEw(Context context) { super(context); } public WrapMyRecyclerVIEw(Context context,@Nullable AttributeSet attrs) { super(context,attrs); } public WrapMyRecyclerVIEw(Context context,@Nullable AttributeSet attrs,int defStyle) { super(context,attrs,defStyle); } /** * 添加headerVIEw * @param v */ public voID addheaderVIEw(VIEw v) { mheaderVIEwInfos.add(v); // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof RecyclerheaderVIEwlistadapter)) { wrapheaderlistadapterInternal(); } } } /** * 添加一个footerVIEw * @param v */ public voID addFooterVIEw(VIEw v) { mFooterVIEwInfos.add(v); // Wrap the adapter if it wasn't already wrapped. if (mAdapter != null) { if (!(mAdapter instanceof RecyclerheaderVIEwlistadapter)) { wrapheaderlistadapterInternal(); } } } /** * 设置一个Adapter * @param adapter */ @OverrIDe public voID setAdapter(Adapter adapter) { if (mheaderVIEwInfos.size() > 0 || mFooterVIEwInfos.size() > 0) { mAdapter = wrapheaderlistadapterInternal(mheaderVIEwInfos,mFooterVIEwInfos,adapter); } else { mAdapter = adapter; } super.setAdapter(mAdapter); } private voID wrapheaderlistadapterInternal() { mAdapter = wrapheaderlistadapterInternal(mheaderVIEwInfos,mAdapter); } /** * 新建一个RecyclerheaderVIEwlistadapter对象 * 最终的adapter实现它 * @param headerVIEwInfos * @param footerVIEwInfos * @param adapter * @return */ protected RecyclerheaderVIEwlistadapter wrapheaderlistadapterInternal( ArrayList<VIEw> headerVIEwInfos,ArrayList<VIEw> footerVIEwInfos,Adapter adapter) { return new RecyclerheaderVIEwlistadapter(headerVIEwInfos,footerVIEwInfos,adapter); }}
这就是封装的RecyclerVIEw,里面主要有三个方法addheaderVIEw、 addFooterVIEw和重写的setAdapter。这里的唯一的思想就是偷梁换柱,当我们添加头部、尾部或者设置adapter时,真正的adapter并不是我们传入的adapter,而是重新new 了一个RecyclerheaderVIEwlistadapter。这才是RecyclerVIEw最终设置的adapter。
其实我们看到ListVIEw也是通过这样子的思想来添加头部和尾部的。
这就是ListVIEw的addheaderVIEw方法,它会偷偷的创建headerVIEwlistadapter这个adapter。最终添加的header和footer在headerVIEwlistadapter里面实现。
public class RecyclerheaderVIEwlistadapter extends RecyclerVIEw.Adapter { private final ArrayList<VIEw> mheaderVIEwInfos;//保存headervIEw数据 private final ArrayList<VIEw> mFooterVIEwInfos;//保存footerVIEw数据 private RecyclerVIEw.Adapter mAdapter; //用户自己构造的adapter private static final int RECYCLER_header_VIEW = 0x001;//headervIEw类型 private static final int RECYCLER_FOOTER_VIEW = 0x002;//footerVIEw类型 /** * 构造方法 * 初始化 * @param headerVIEwInfos * @param footerVIEwInfos * @param adapter */ public RecyclerheaderVIEwlistadapter(ArrayList<VIEw> headerVIEwInfos,RecyclerVIEw.Adapter adapter) { mAdapter = adapter; if (headerVIEwInfos == null) { mheaderVIEwInfos = new ArrayList<>(); } else { mheaderVIEwInfos = headerVIEwInfos; } if (footerVIEwInfos == null) { mFooterVIEwInfos = new ArrayList<>(); } else { mFooterVIEwInfos = footerVIEwInfos; } } /** * 根据getItemVIEwType返回的条目类型 * 创建不同的itemvIEw * 传入的adapter,回调它的onCreateVIEwHolder即可 * @param parent * @param vIEwType * @return */ @OverrIDe public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,int vIEwType) { if (vIEwType == RECYCLER_header_VIEW){ return new headerVIEwLayout(mheaderVIEwInfos.get(0)); }else if (vIEwType == RECYCLER_FOOTER_VIEW){ return new headerVIEwLayout(mFooterVIEwInfos.get(0)); } return mAdapter.onCreateVIEwHolder(parent,vIEwType); } /** * 绑定数据 * headervIEw和footervIEw不需要绑定数据,直接return即可 * 传入的adapter需要回调它的onBindVIEwHolder即可 * @param holder * @param position */ @OverrIDe public voID onBindVIEwHolder(RecyclerVIEw.VIEwHolder holder,int position) { //header int numheaders = getheadersCount(); if (position < numheaders) { return ; } //adapter body final int adjposition = position - numheaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getItemCount(); if (adjposition < adapterCount) { mAdapter.onBindVIEwHolder(holder,adjposition); return ; } } //footer } /** * 返回条目的类型 * 传入的adapter,回调它的getItemVIEwType即可 * @param position * @return */ @OverrIDe public int getItemVIEwType(int position) { // header int numheaders = getheadersCount(); if (position < numheaders) { return RECYCLER_header_VIEW; } // Adapter final int adjposition = position - numheaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getItemCount(); if (adjposition < adapterCount) { return mAdapter.getItemVIEwType(position); } } // Footer (off-limits positions will throw an indexoutofboundsexception) return RECYCLER_FOOTER_VIEW; } /** * 总条目即:footervIEw的条目+headervIEw的条目+穿入的adapter条目 * @return */ @OverrIDe public int getItemCount() { if (mAdapter != null) { return getFootersCount() + getheadersCount() + mAdapter.getItemCount(); } else { return getFootersCount() + getheadersCount(); } } /** * 获取headervIEw的条目 * @return */ public int getheadersCount() { return mheaderVIEwInfos.size(); } /** * 获取footervIE的条目 * @return */ public int getFootersCount() { return mFooterVIEwInfos.size(); } /** * 这是footervIEw和headervIEw的VIEwHolder需要 * 这里只是提供一个构造器即可,实际上用处不大 */ private static class headerVIEwLayout extends RecyclerVIEw.VIEwHolder{ public headerVIEwLayout(VIEw itemVIEw) { super(itemVIEw); } }}
这是实现添加header、footer和传入adapter的RecyclerheaderVIEwlistadapter。具体的逻辑都在文件的注释里面有说明。逻辑是仿造ListVIEw的headerVIEwlistadapter来实现的。
其实就是创建一个adapter,然后根据不同的条目类型来创建条目和绑定条目的数据即可。
<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:tools="http://schemas.androID.com/tools" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:orIEntation="vertical" tools:context="com.wrap.recycler.WrapRecyclerVIEwActivity"> <com.lwj.wrap.recycler.WrapMyRecyclerVIEw androID:ID="@+ID/wrap_recyclervIEw" androID:layout_wIDth="match_parent" androID:layout_height="match_parent"/></linearLayout>
这是布局文件
public class WrapRecyclerVIEwActivity extends AppCompatActivity { private WrapMyRecyclerVIEw mRecyclerVIEw; private MyAdapter mMyAdapter; private List<String> mList01 = new ArrayList<>(); private static final int WC = VIEwGroup.LayoutParams.WRAP_CONTENT; @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_wrap_recycler_vIEw); getData(); mRecyclerVIEw = (WrapMyRecyclerVIEw) this.findVIEwByID(R.ID.wrap_recyclervIEw); mRecyclerVIEw.setLayoutManager(new linearlayoutmanager(this)); //加入headerVIEw VIEwGroup.LayoutParams params = new VIEwGroup.LayoutParams(WC,WC); ImageVIEw headerVIEw = new ImageVIEw(this); headerVIEw.setimageResource(R.drawable.timg); headerVIEw.setLayoutParams(params); mRecyclerVIEw.addheaderVIEw(headerVIEw); //设置adapter mMyAdapter = new MyAdapter(this,mList01); mRecyclerVIEw.setAdapter(mMyAdapter); //加入footerVIEw params = new VIEwGroup.LayoutParams(WC,WC); ImageVIEw footerVIEw = new ImageVIEw(this); footerVIEw.setimageResource(R.drawable.hhfj); footerVIEw.setLayoutParams(params); mRecyclerVIEw.addFooterVIEw(footerVIEw); mMyAdapter.notifyDataSetChanged(); } public voID getData() { for (int i = 0; i < 3; i++) { String data ="adapter...." + i; mList01.add(data); } }}
使用直接调用addheaderVIEw、addFooterVIEw即可。
除了这种方式来实现addheaderVIEw和addFooterVIEw,另外一种方式就是封装Adapter来实现,原理还是保持不变:根据不同的条目类型来创建条目和绑定条目的数据。
public class MyCircleRecycVIEwAdapter extends RecyclerVIEw.Adapter { public List<CircleInfo.CirclePageInfo> infos = null; private Context mContext; private ListVIEwimgLoader mloader; private VIEw VIEW_FOOTER;//尾部 private VIEw VIEW_header;//头部 //Type private int TYPE_norMAL = 1000; private int TYPE_header = 1001; private int TYPE_FOOTER = 1002; private int tagType = TYPE_norMAL; public MyCircleRecycVIEwAdapter(Context context,List<CircleInfo.CirclePageInfo> datas) { this.infos = datas; this.mContext = context; mloader = new ListVIEwimgLoader(); mloader.setMemoryCacheSize(1024 * 1024); mloader.setVisibleItemCount(12); } @OverrIDe public RecyclerVIEw.VIEwHolder onCreateVIEwHolder(VIEwGroup parent,int vIEwType) { if (vIEwType == TYPE_FOOTER) { tagType = TYPE_FOOTER; return new MyCircleItemHolder(VIEW_FOOTER); } else if (vIEwType == TYPE_header) { tagType = TYPE_header; return new MyCircleItemHolder(VIEW_header); } else { tagType = TYPE_norMAL; VIEw vIEw = LayoutInflater.from(mContext).inflate(R.layout.circle_grIDvIEw_items,parent,false); return new MyCircleItemHolder(vIEw); } } @OverrIDe public voID onBindVIEwHolder(RecyclerVIEw.VIEwHolder holder,int position) { if (!isheaderVIEw(position) && !isFooterVIEw(position)) { if (haveheaderVIEw()) position--; MyCircleItemHolder vIEwHolder = (MyCircleItemHolder)holder; CircleInfo.CirclePageInfo mInfo = infos.get(position); setData(vIEwHolder,mInfo); } } @OverrIDe public int getItemCount() { int count = (infos == null ? 0 : infos.size()); if (VIEW_FOOTER != null) { count++; } if (VIEW_header != null) { count++; } return count; } @OverrIDe public int getItemVIEwType(int position) { if (isheaderVIEw(position)) { return TYPE_header; } else if (isFooterVIEw(position)) { return TYPE_FOOTER; } else { return TYPE_norMAL; } } public voID addheaderVIEw(VIEw headerVIEw) { if (haveheaderVIEw()) { throw new IllegalStateException("hearvIEw has already exists!"); } else { //避免出现宽度自适应 VIEwGroup.LayoutParams params = new VIEwGroup.LayoutParams(Utils.getRealPixel(30),Utils.getRealPixel(230)); headerVIEw.setLayoutParams(params); VIEW_header = headerVIEw; notifyItemInserted(0); } } public voID addFooterVIEw(VIEw footerVIEw) { if (haveFooterVIEw()) { throw new IllegalStateException("footerVIEw has already exists!"); } else { VIEwGroup.LayoutParams params = new VIEwGroup.LayoutParams(VIEwGroup.LayoutParams.MATCH_PARENT,VIEwGroup.LayoutParams.WRAP_CONTENT); footerVIEw.setLayoutParams(params); VIEW_FOOTER = footerVIEw;// ifGrIDLayoutManager(); notifyItemInserted(getItemCount() - 1); } } private boolean haveheaderVIEw() { return VIEW_header != null; } public boolean haveFooterVIEw() { return VIEW_FOOTER != null; } private boolean isheaderVIEw(int position) { return haveheaderVIEw() && position == 0; } private boolean isFooterVIEw(int position) { return haveFooterVIEw() && position == getItemCount() - 1; } private voID setData(final MyCircleItemHolder vIEwHolder,final CircleInfo.CirclePageInfo mInfo) { if(mInfo == null || mInfo == vIEwHolder.tagInfo) { return; }else{ vIEwHolder.tagInfo = mInfo; if(!StrUtils.isEnpty(mInfo.thread_unread)){ if(mInfo.thread_unread.equals("0")){ vIEwHolder.threaduUnreadTv.setVisibility(VIEw.INVISIBLE); }else{ vIEwHolder.threaduUnreadTv.setVisibility(VIEw.VISIBLE); vIEwHolder.threaduUnreadTv.setText(mInfo.thread_unread); } }else{ vIEwHolder.threaduUnreadTv.setVisibility(VIEw.INVISIBLE); } if (!TextUtils.isEmpty(vIEwHolder.tagUrl)){ if(mInfo.circle_img_path != null && !(mInfo.circle_img_path.equals(vIEwHolder.tagUrl))){ setimage(vIEwHolder.mImageVIEw,mInfo.circle_img_path); } }else{ setimage(vIEwHolder.mImageVIEw,mInfo.circle_img_path); } if (!TextUtils.isEmpty(mInfo.circle_img_path)){ vIEwHolder.tagUrl = mInfo.circle_img_path; } if(mInfo.circlename != null){ if(mInfo.circlename.length() > 5){ String s = mInfo.circlename.substring(0,5) + "..."; vIEwHolder.textVIEw.setText(s); }else{ vIEwHolder.textVIEw.setText(mInfo.circlename); } } } } private voID setimage(final colorFilterImageVIEw mImageVIEw,final String imgurl){ mImageVIEw.setBackgroundcolor(0xffadadad); mImageVIEw.setimageBitmap(null); if(!TextUtils.isEmpty(imgurl)) { mloader.loadImage(mImageVIEw.hashCode(),imgurl,300,new Dnimg.OnDnimgListener() { @OverrIDe public voID onProgress(String url,int downloadedSize,int totalSize) { // Todo auto-generated method stub } @OverrIDe public voID onFinish(String url,String file,Bitmap bmp) { if(url.equals(imgurl)) { mImageVIEw.setimageBitmap(bmp); } } }); }else{ mImageVIEw.setBackgroundcolor(0xffadadad); mImageVIEw.setimageBitmap(null); } } class MyCircleItemHolder extends RecyclerVIEw.VIEwHolder{ private colorFilterImageVIEw mImageVIEw; private TextVIEw textVIEw; private CircleInfo.CirclePageInfo tagInfo; private String tagUrl; private TextVIEw threaduUnreadTv; public MyCircleItemHolder(final VIEw itemVIEw) { super(itemVIEw); if(tagType == TYPE_norMAL){ mImageVIEw = (colorFilterImageVIEw)itemVIEw.findVIEwByID(R.ID.quan_icon); mImageVIEw.setScaleType(ImageVIEw.ScaleType.CENTER_CROP); textVIEw = (TextVIEw)itemVIEw.findVIEwByID(R.ID.quan_name); threaduUnreadTv = (TextVIEw)itemVIEw.findVIEwByID(R.ID.quan_num); mImageVIEw.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { if (mListener != null){ mListener.oncliItem(itemVIEw,tagInfo,threaduUnreadTv); } } }); } } } public OnclickMyCircleItemListener mListener; public voID setonclickMyCircleItemListener(OnclickMyCircleItemListener l){ this.mListener = l; } public interface OnclickMyCircleItemListener{ voID oncliItem(VIEw vIEw,CircleInfo.CirclePageInfo info,VIEw threadNumTv); } public voID pauseLoader(){ if(mloader != null) { mloader.pause(); } } public voID resumeLoader(){ if(mloader != null) { mloader.resume(); } } public voID closeLoader(){ if(mloader != null) { mloader.close(); } }}
总结
以上就是这篇文章的全部内容了,希望本文的内容对各位AndroID开发者们的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持。
以上是内存溢出为你收集整理的Android中封装RecyclerView实现添加头部和底部示例代码全部内容,希望文章能够帮你解决Android中封装RecyclerView实现添加头部和底部示例代码所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)