RecyclerView添加Header和Footer
2017-07-31 20:09
225 查看
本篇博客借鉴了 亓斌 大神的, RecyclerView添加Header的正确方式
自己想做一个类似微信的联系人界面,想到的解决方案就是在recyclerView添加header和footer。
做出来的效果如下:(界面有些丑,轻喷)
添加footer的时候也遇到了坑,最开始直接修改了getItemViewType方法,获得footer类型,和onCreateViewHolder方法里面加入创建footer的ViewHolder
@Override public int getItemViewType(int position) { if (mHeaderView == null) return TYPE_NORMAL; if (position == 0) return TYPE_HEADER; if (mFooterView == null) return TYPE_NORMAL; if (position == getItemCount() - 1) return TYPE_FOOTER; return TYPE_NORMAL; }
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) { if (mFooterView != null && viewType == TYPE_FOOTER) return new ViewHolder(mFooterView); if (mHeaderView != null && viewType == TYPE_HEADER) return new ViewHolder(mHeaderView); return onCreate(parent, viewType); }
做了10个假数据后,拖动只可以看到8条数据。想想肯定是总数getItemCount方法的返回值有问题了
@Override public int getItemCount() { int itemCount = mDatas.size(); if (mHeaderView != null ) { itemCount ++ ; } if (mFooterView != null) { itemCount ++; } return itemCount; }修改后,继续重新运行,运行到recyclerView的第8个Item在拖动就报ClassCastException。
找了好久也没找到是哪里的问题,后来经过debug发现,在onBindViewHolder里面的第一行代码进行了对header类型的Item进行的return,想想自己也应该加上。
@Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { //防止出现ClassCastException if (getItemViewType(position) == TYPE_HEADER) return; if (getItemViewType(position) == TYPE_FOOTER) return; int pos = getRealPosition(viewHolder); T data = null; //对数据进行判空,以免出现异常 if (mDatas != null && mDatas.size() > 0) { data = mDatas.get(pos); onBind(viewHolder, pos, data); } if (mListener != null) { final T finalData = data; final int finalPos = pos; viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mListener.onItemClick(finalPos, finalData); } }); } }由于自己做的是联系人,在增加联系人后对数据要进行重新绑定,所以自己添加了onBindData方法,对recyclerView的数据重新赋值。
整体代码如下:
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public static final int TYPE_HEADER = 0; public static final int TYPE_NORMAL = 1; public static final int TYPE_FOOTER = 2; public Context context; public List<T> mDatas; public BaseRecyclerAdapter(Context context, List<T> datas) { this.context = context; this.mDatas = datas; } private View mHeaderView; public View mFooterView; private OnItemClickListener mListener; public void setOnItemClickListener(OnItemClickListener listener) { mListener = listener; } /** * 只可以添加一次headerView * @param headerView */ public void setHeaderView(View headerView) { mHeaderView = headerView; notifyItemInserted(0); } public View getHeaderView() { return mHeaderView; } /** * 只可以添加一次footView * @param footerView */ public void setFooterView(View footerView) { mFooterView = footerView; notifyItemInserted(getItemCount()); } public View getFooterView() { return mFooterView; } @Override public int getItemViewType(int position) { if (mHeaderView == null) return TYPE_NORMAL; if (position == 0) return TYPE_HEADER; if (mFooterView == null) return TYPE_NORMAL; if (position == getItemCount() - 1) return TYPE_FOOTER; return TYPE_NORMAL; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, final int viewType) { if (mFooterView != null && viewType == TYPE_FOOTER) return new ViewHolder(mFooterView); if (mHeaderView != null && viewType == TYPE_HEADER) return new ViewHolder(mHeaderView); return onCreate(parent, viewType); } @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { //防止出现ClassCastException if (getItemViewType(position) == TYPE_HEADER) return; if (getItemViewType(position) == TYPE_FOOTER) return; int pos = getRealPosition(viewHolder); T data = null; //对数据进行判空,以免出现异常 if (mDatas != null && mDatas.size() > 0) { data = mDatas.get(pos); onBind(viewHolder, pos, data); } if (mListener != null) { final T finalData = data; final int finalPos = pos; viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mListener.onItemClick(finalPos, finalData); } }); } } @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 getItemViewType(position) == TYPE_HEADER ? gridManager.getSpanCount() : 1; } }); } } @Override public void onViewAttachedToWindow(Rec 4000 yclerView.ViewHolder viewHolder) { super.onViewAttachedToWindow(viewHolder); ViewGroup.LayoutParams lp = viewHolder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(viewHolder.getLayoutPosition() == 0); } } /** * 得到真正的位置position * @param holder * @return */ public int getRealPosition(RecyclerView.ViewHolder holder) { int position = holder.getLayoutPosition(); return mHeaderView == null ? position : position - 1; } /** * 得到recyclerView中的item总数 */ @Override public int getItemCount() { int itemCount = mDatas.size(); if (mHeaderView != null ) { itemCount ++ ; } if (mFooterView != null) { itemCount ++; } return itemCount; } /** * 得到recyclerView中的真正数据总数 */ public int getRealItemCount(){ return mDatas.size(); } public abstract RecyclerView.ViewHolder onCreate(ViewGroup parent, final int viewType); public abstract void onBind(RecyclerView.ViewHolder viewHolder, int realPosition, T data); public abstract void bindDatas(List<T> allNewFriend); public class ViewHolder extends RecyclerView.ViewHolder { public ViewHolder(View itemView) { super(itemView); } } public interface OnItemClickListener<T> { void onItemClick(int position, T data); } }使用方法:
public class AddressListPagerAdapter extends BaseRecyclerAdapter<Friend> { public AddressListPagerAdapter(Context context, List<Friend> datas) { super(context, datas); } @Override public RecyclerView.ViewHolder onCreate(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.address_list_item, parent, false); return new ViewHolder(itemView); } @Override public void onBind(RecyclerView.ViewHolder viewHolder, int realPosition, Friend data) { ((ViewHolder) viewHolder).tv_friend_name.setText(mDatas.get(realPosition).getUsername()); RequestOptions requestOptions = new RequestOptions() .placeholder(R.drawable.head) .error(R.drawable.default_head); Glide.with(context).load(mDatas.get(realPosition).getHeaderImage()) .apply(requestOptions) .into(((ViewHolder) viewHolder).iv_head_portrait); } @Override public void bindDatas(List<Friend> allNewFriend) { mDatas = allNewFriend; } public class ViewHolder extends BaseRecyclerAdapter.ViewHolder { private ImageView iv_head_portrait; private TextView tv_friend_name; public ViewHolder(View itemView) { super(itemView); iv_head_portrait = (ImageView) itemView.findViewById(R.id.iv_head_portrait); tv_friend_name = (TextView) itemView.findViewById(R.id.tv_friend_name); } } }
添加Header和Footer直接调用,setHeaderView和setFooterView方法既可以,header和footer点击事件没有在recyclerView里面进行处理,需要自己进行设置,个人感觉脱离了recyclerView的header和footer的点击事件处理起来更好一些,个人观点可能有点片面,不过应该具体情况具体分析吧。
唯一的一点遗憾就是在onBind里面进行绑定数据的时候需要对viewHolder进行强转。还有这样的方法只能添加一个header和一个footer,如果想多添加,可以将对应的view添加到header和footer中。如果还是不能满足你的需求,可以借鉴鸿洋_大神的方法
相关文章推荐
- RecyclerView的使用(3)之添加Header和Footer
- 封装RecyclerView Adapter 实现可添加多个header和footer,可设置loadingView,低耦合的多种布局。
- 为RecyclerView添加header和footer
- RecyclerView系列之(1):为RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- 参考ListView为RecyclerView添加Header、Footer和Loader
- RecyclerView系列之(1):为RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView封装——添加Header、Footer(在网格瀑布流布局中独占一行)
- RecyclerView的使用(3)之添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer的方法
- 使用RecyclerView添加Header和Footer的方法
- RecyclerView添加Header和Footer的基本原理
- 一个精简的实现RecyclerView可添加header和footer的Demo
- 使用RecyclerView添加Header和Footer的方法
- 优雅的为RecyclerView添加头尾布局HeaderAndFooterWrapper
- 一款下拉刷新以及上拉加载的控件库,扩展性强,使用简单。并附带有可以添加 header 和 footer 的 Recyclerview
- 一个能一句话添加header和Footer,并且能滑动删除和交换Item的RecyclerView