为RecyclerView添加Header和Footer,支持三种LayoutManager
2017-07-06 17:43
393 查看
public abstract class RecyclerHeaderFooterAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> { private static final int ITEM_TYPE_HEADER = 1; private static final int ITEM_TYPE_FOOTER = 2; private boolean headerEnable; private boolean footerEnable; private boolean singleLineHeaderEnable; private boolean singleLineFooterEnable; private OnItemClickListener onItemClickListener; private OnItemLongLickListener onItemLongLickListener; @Override public final VH onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == ITEM_TYPE_HEADER) { return onCreateHeaderViewHolder(parent, viewType); } else if (viewType == ITEM_TYPE_FOOTER) { return onCreateFooterViewHolder(parent, viewType); } else { return onCreateContentViewHolder(parent, viewType - ITEM_TYPE_HEADER - ITEM_TYPE_FOOTER); } } @Override public final void onBindViewHolder(final VH holder, final int position) { int viewType = holder.getItemViewType(); if (viewType == ITEM_TYPE_HEADER) { onBindHeaderViewHolder(holder, position); } else if (viewType == ITEM_TYPE_FOOTER) { final int headerCount = isHeaderEnable() ? getHeaderItemCount() : 0; final int contentCount = getContentItemCount(); onBindFooterViewHolder(holder, position - headerCount - contentCount); } else { final int headerCount = isHeaderEnable() ? getHeaderItemCount() : 0; onBindContentViewHolder(holder, position - headerCount); if (onItemClickListener != null) { holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(holder, position - headerCount); } }); } if (onItemLongLickListener != null) { holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return onItemLongLickListener.onItemLongClick(holder, position - headerCount); } }); } } } @Override public final long getItemId(int position) { final int validHeaderCount = isHeaderEnable() ? getHeaderItemCount() : 0; final int contentItemCount = getContentItemCount(); if (position < validHeaderCount) { return getHeaderItemId(position); } else if (position < validHeaderCount + contentItemCount) { return getContentItemId(position - validHeaderCount); } else { return getContentItemId(position - validHeaderCount - contentItemCount); } } @Override public final int getItemCount() { int itemCount = 0; if (isHeaderEnable()) { itemCount += getHeaderItemCount(); } if (isFooterEnable()) { itemCount += getFooterItemCount(); } itemCount += getContentItemCount(); return itemCount; } @Override public final int getItemViewType(int position) { final int validHeaderCount = isHeaderEnable() ? getHeaderItemCount() : 0; if (position < validHeaderCount) { return ITEM_TYPE_HEADER; } else if (position < validHeaderCount + getContentItemCount()) { int contentItemViewType = getContentItemViewType(position - validHeaderCount); if (contentItemViewType <= 0) { throw new IllegalArgumentException("getContentItemViewType must return a value > 0"); } return contentItemViewType + ITEM_TYPE_HEADER + ITEM_TYPE_FOOTER; } else { return ITEM_TYPE_FOOTER; } } public VH onCreateHeaderViewHolder(ViewGroup parent, int viewType) { return null; } public VH onCreateFooterViewHolder(ViewGroup parent, int viewType) { return null; } public abstract VH onCreateContentViewHolder(ViewGroup parent, int viewType); public abstract void onBindContentViewHolder(VH holder, int position); public void onBindFooterViewHolder(VH holder, int position) { } public void onBindHeaderViewHolder(VH holder, int position) { } public int getHeaderItemCount() { return 0; } public int getFooterItemCount() { return 0; } public abstract int getContentItemCount(); public int getContentItemViewType(int position) { return 1; } protected long getContentItemId(int position) { return RecyclerView.NO_ID; } protected long getFooterItemId(int position) { return RecyclerView.NO_ID; } protected long getHeaderItemId(int position) { return RecyclerView.NO_ID; } public final boolean isHeaderEnable() { return headerEnable; } public void setHeaderEnable(boolean headerEnable) { if (!(isHeaderEnable() && headerEnable)) { notifyDataSetChanged(); this.headerEnable = headerEnable; } } public final boolean isFooterEnable() { return footerEnable; } public void setFooterEnable(boolean footerEnable) { if (!(isFooterEnable() && footerEnable)) { final int validHeaderCount = isHeaderEnable() ? getHeaderItemCount() : 0; notifyItemRangeRemoved(validHeaderCount + getContentItemCount(), getFooterItemCount()); this.footerEnable = footerEnable; } } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } public void setOnItemLongLickListener(OnItemLongLickListener onItemLongLickListener) { this.onItemLongLickListener = onItemLongLickListener; } public boolean isHeaderItem(int position){ return isHeaderEnable() && position < getHeaderItemCount(); } public boolean isContentItem(int position){ final int validHeaderCount = isHeaderEnable() ? getHeaderItemCount() : 0; final int validFooterCount = isFooterEnable() ? getFooterItemCount() : 0; return position >= validHeaderCount && position < getItemCount() - validFooterCount; } public boolean isFooterItem(int position){ final int validHeaderCount = isHeaderEnable() ? getHeaderItemCount() : 0; return position >= getItemCount() - getContentItemCount()- validHeaderCount; } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if(layoutManager instanceof GridLayoutManager){ final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; final GridLayoutManager.SpanSizeLookup oldSizeLookup = gridLayoutManager.getSpanSizeLookup(); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if(isHeaderItem(position) && singleLineHeaderEnable){ return gridLayoutManager.getSpanCount(); } if(isFooterItem(position) && singleLineFooterEnable){ return gridLayoutManager.getSpanCount(); } if(oldSizeLookup != null){ return oldSizeLookup.getSpanSize(position); } return 0; } }); } } @Override public void onViewAttachedToWindow(VH holder) { super.onViewAttachedToWindow(holder); int position = holder.getLayoutPosition(); if (isHeaderItem(position) && singleLineHeaderEnable || isFooterItem(position) && singleLineFooterEnable) { ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } } public boolean isSingleLineHeaderEnable() { return singleLineHeaderEnable; } public void setSingleLineHeaderEnable(boolean singleLineHeaderEnable) { this.singleLineHeaderEnable = singleLineHeaderEnable; } public boolean isSingleLineFooterEnable() { return singleLineFooterEnable; } public void setSingleLineFooterEnable(boolean singleLineFooterEnable) { this.singleLineFooterEnable = singleLineFooterEnable; }
相关文章推荐
- XAdapter:支持下拉刷新加载和添加多个header和footer的RecyclerViewAdapter
- 从头开始学 RecyclerView(四) 类ListView添加header和footer、多种ViewHolder的支持
- recyclerView通用适配器,支持添加多个header和footer
- 一款下拉刷新以及上拉加载的控件库,扩展性强,使用简单。并附带有可以添加 header 和 footer 的 Recyclerview
- 如何为RecyclerView添加Header和Footer
- 你必须了解的 RecyclerView 的五大开源项目 - 解决上拉加载、下拉刷新和添加 Header、Footer 等问题
- 你必须了解的RecyclerView的五大开源项目-解决上拉加载、下拉刷新和添加Header、Footer等问题
- 基于RecyclerView的封装,仿qq侧拉删除效果,实现下拉刷新,上拉加载更多,添加header,添加footer
- RecyclerView系列之(1):为RecyclerView添加Header和Footer
- RecyclerView的使用(3)之添加Header和Footer
- 你必须了解的RecyclerView的五大开源项目-解决上拉加载、下拉刷新和添加Header、Footer等问题
- 给RecyclerView添加header和footer
- RecyclerView添加Header和Footer
- RecyclerView 添加 Footer and Header
- 一个能一句话添加header和Footer,并且能滑动删除和交换Item的RecyclerView
- 你必须了解的 RecyclerView 的五大开源项目 - 解决上拉加载、下拉刷新和添加 Header、Footer 等问题
- 为RecyclerView添加header和footer
- RecyclerView添加header和footer
- 一个精简的实现RecyclerView可添加header和footer的Demo
- 你必须了解的RecyclerView的五大开源项目-解决上拉加载、下拉刷新和添加Header、Footer等问题