优雅的给RecyclerView增加多个headerView

我们都知道Listview可以调用addHeaderViewaddFootView来添加头尾信息,轻松实现如苏宁易购首页,淘宝首页那种有多个HeaderView的列表形式。RecyclerView现在在项目中基本都替代ListViewGridView了,然而我们新的RecyclerView却没有自带这个功能。那只有自己去撸一个了。

实现思路

  • 在Adapter里面新建两个列表mHeaderViews及mFooterViews把加入的Header及Footer保存起来*
  • 把Header及Footer当作正常item
  • 复写getItemViewType方法,通过position返回不同类型:0为原本的内容,大于0为Header, 小于0为Footer
  • 复写onCreateViewHolder方法。当position为0 ~ header.size-1时返回mHeaderViews的对象,header.size~header.size+count-1时为原有内容,另外就是footer了

复写adapter问题

通过复写adapter功能可以实现,但此库没有通用性,每次我们都得重新写一下增加header的相关逻辑,通过装饰器对adapter进行包装达到通用的效果

实现代码

HeaderRecyclerView.java

package com.yy.recycleview;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;

public class HeaderRecyclerView extends RecyclerView {
    //头view的集合
    private ArrayList<HeaderViewHolder> mHeaderViewInfos=new ArrayList<>();
    //脚view的集合
    private ArrayList<HeaderViewHolder> mFooterViewInfos=new ArrayList<>();

    private Adapter mAdapter;

    public HeaderRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }
    public void addHeaderView(View v) {
        mHeaderViewInfos.add(new HeaderViewHolder(v));
        // 如果适配器未初始
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {
                mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
            }
        }
    }

    public void addFooterView(View v) {
        mFooterViewInfos.add(new HeaderViewHolder(v));
        // 如果适配器未初始
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {
                mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
            }
        }
    }

    @Override
    public void setAdapter(Adapter adapter) {
        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }
        super.setAdapter(mAdapter);
    }

}

HeaderViewHolder.java

package com.yy.recycleview;

import android.support.v7.widget.RecyclerView;
import android.view.View;

public class HeaderViewHolder extends  RecyclerView.ViewHolder{

    public HeaderViewHolder(View itemView) {
        super(itemView);
    }
}

HeaderViewRecyclerAdapter

package com.yy.recycleview;

import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;

import java.util.ArrayList;
public class HeaderViewRecyclerAdapter extends RecyclerView.Adapter {
    /**
     *  头条目返回大于0的数据,尾显示小于0的数据类型
     */

    private ArrayList<HeaderViewHolder> mHeaderViews;
    private ArrayList<HeaderViewHolder> mFooterViews;
    private RecyclerView.Adapter mAdapter;

    public HeaderViewRecyclerAdapter(ArrayList<HeaderViewHolder> haderViews, ArrayList<HeaderViewHolder> footerViews, RecyclerView.Adapter mAdapter) {
        if (haderViews == null) {
            mHeaderViews = new ArrayList<HeaderViewHolder>();
        } else {
            mHeaderViews = haderViews;
        }

        if (footerViews == null) {
            mFooterViews = new ArrayList<HeaderViewHolder>();
        } else {
            mFooterViews = footerViews;
        }
        this.mAdapter=mAdapter;
    }

    @Override
    public int getItemViewType(int position) {
        //header 类型为正数,通过type可以换算出position
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return position+1;
        }
        // Adapter 正常为0
        final int realPosition = position - numHeaders;
        int realAdapterCount = 0;
        if (mAdapter != null) {
            realAdapterCount = mAdapter.getItemCount();
            if (realPosition < realAdapterCount) {
                return mAdapter.getItemViewType(realPosition);
            }
        }
        // Footer 用负数表示类型
        return  -(position-numHeaders-realAdapterCount)-1;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        int index;
        if(viewType==0)return mAdapter.onCreateViewHolder(parent,viewType);
        else if(viewType>0){
            index=viewType-1;
            return mHeaderViews.get(index);
        }
        else{
            index=index=-viewType-1;
            return mFooterViews.get(index);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        //也要划分三个区域
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {//是头部
            return;
        }
        //原来的adapter正常内容
        final int realPosition = position - numHeaders;
        int adapterCount = 0;
        if (mAdapter != null) {
            adapterCount = mAdapter.getItemCount();
            if (realPosition < adapterCount) {
                mAdapter.onBindViewHolder(holder, realPosition);
                return;
            }
        }
        //尾部

    }

    @Override
    public int getItemCount() {
        if (mAdapter != null) {
            return getFootersCount() + getHeadersCount() + mAdapter.getItemCount();
        } else {
            return getFootersCount() + getHeadersCount();
        }
    }

    /**
     *
     * @return Header的个数
     */
    public int getHeadersCount() {
        return mHeaderViews.size();
    }

    /**
     * footer的个数
     * @return
     */
    public int getFootersCount() {
        return mFooterViews.size();
    }
}

Demo请移步https://github.com/kx1115/HeaderAndFooterRecycleViewDemo

    原文作者:waiwaaa
    原文地址: https://www.jianshu.com/p/400da78b1b73
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞