为RecyclerView添加Header和Footer,支持三种LayoutManager

来源:互联网 发布:南方数据粘贴 编辑:程序博客网 时间:2024/05/29 10:42
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;    }