Android中封装RecyclerView实现添加头部和底部示例代码

Android中封装RecyclerView实现添加头部和底部示例代码,第1张

概述前言我们大家都知道ListView具有添加头部和添加底部的方法,但是RecyclerView并没有这样子的方法。所以RecyclerView是不能添加底部和头部的,但是能不能仿造ListView来实现RecyclerView添加头部和底部呢?答案当然是

前言

我们大家都知道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实现添加头部和底部示例代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1144718.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存