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

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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值