recyclerView通用适配器,支持添加多个header和footer

recyclerView通用适配器,支持添加多个header和footer

每个RecyclerView都要写一个适配器很浪费时间。

  1. 设置header和footer就是RecyclerView设置不同type的Item。
  2. onCreatedViewHolder()绑定不同布局(item),抽象出一个方法getItemLayoutId()。
  3. 绑定数据onBindViewHolder中设置了一个onBind()方法。
  4. 给item设置点击事件,已经把header和footer的item的点击事件屏蔽了

以下是全部代码:

package com.lanjiejie.adapter;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * recyclerView 适配器
 */

public abstract class BaseRecycleViewAdapter<T> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {

    public static final int TYPE_NORMAL = 1;
    private static final int TYPE_FLAG = 100000;

    private Context mContext;
    private List<T> mDataList;
    private LayoutInflater mLayoutInflater;
    private List<View> mHeaderViews = new ArrayList<>();
    private List<View> mFooterViews = new ArrayList<>();

    private List<Integer> mHeaderViewTypes = new ArrayList<>();
    private List<Integer> mFooterViewTypes = new ArrayList<>();

    private OnItemClickListener mClickListener;


    public BaseRecycleViewAdapter(Context context, List<T> dataList) {
        this.mContext = context;
        this.mDataList = dataList;
        mLayoutInflater = LayoutInflater.from(mContext);
    }

    @Override
    public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mHeaderViewTypes.contains(viewType)) {
            return new BaseRecyclerViewHolder(mContext, mHeaderViews.get(viewType / TYPE_FLAG));
        }

        if (mFooterViewTypes.contains(viewType)) {
            int index = viewType / TYPE_FLAG - mDataList.size() - mHeaderViews.size();
            return new BaseRecyclerViewHolder(mContext, mFooterViews.get(index));
        }

        return new BaseRecyclerViewHolder(mContext, mLayoutInflater.inflate(getItemLayoutId(viewType), parent, false));
    }

    @Override
    public void onBindViewHolder(final BaseRecyclerViewHolder holder, final int position) {

        if (isFooter(position) || isHeader(position))
            return;
        final int realPos = getRealPosition(position);
        if (realPos < mDataList.size()) {
            final T data = mDataList.get(realPos);
            onBind(holder, realPos, data);
        }
        if (mClickListener != null) {

            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mClickListener.onItemClick(holder.itemView, realPos);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return mDataList.size() + mHeaderViews.size() + mFooterViews.size();
    }

    @Override
    public int getItemViewType(int position) {
        if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
            //用position作为HeaderView 的   ViewType标记
            //记录每个ViewType标记
            mHeaderViewTypes.add(position * TYPE_FLAG);
            return position * TYPE_FLAG;
        }

        if (mFooterViews.size() > 0 && mFooterViews.size() > 0 && position >= getItemCount() - mFooterViews.size()) {
            //用position作为FooterView 的   ViewType标记
            //记录每个ViewType标记
            mFooterViewTypes.add(position * TYPE_FLAG);
            return position * TYPE_FLAG;
        }
        return TYPE_NORMAL;
    }

    public int getRealPosition(int position) {
        return position - mHeaderViews.size();
    }

    /**
     * 必须在setAdapter之前添加
     *
     * @param view header
     */
    public void addHeaderView(View view) {
        mHeaderViews.add(view);
    }

    /**
     * 必须在setAdapter之前添加
     *
     * @param view footer
     */
    public void addFooterView(View view) {
        mFooterViews.add(view);
    }

    private boolean isHeader(int position) {
        return mHeaderViews.size() > 0 && position < mHeaderViews.size();
    }

    private boolean isFooter(int position) {
        return mFooterViews.size() > 0 && position >= getItemCount() - mFooterViews.size();
    }

    /**
     * 当LayoutManager是GridLayoutManager时,设置header和footer占据的列数
     * @param recyclerView recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) layoutManager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return (isFooter(position) || isHeader(position))
                            ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    /**
     * 当LayoutManager是StaggeredGridLayoutManager时,设置header和footer占据的列数
     * @param holder holder
     */
    @Override
    public void onViewAttachedToWindow(BaseRecyclerViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        final ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
        if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
            StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) layoutParams;
            params.setFullSpan(isHeader(holder.getLayoutPosition())
                    || isFooter(holder.getLayoutPosition()));
        }
    }

    /**
     * 绑定数据
     * @param viewHolder holder
     * @param position pos
     * @param data 数据源
     */
    public abstract void onBind(BaseRecyclerViewHolder viewHolder, int position, T data);

    /**
     * item 布局id
     *
     * @param viewType item type
     * @return item 布局id
     */
    abstract public int getItemLayoutId(int viewType);

    public interface OnItemClickListener {
        void onItemClick(View itemView, int pos);

        void onItemLongClick(View itemView, int pos);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mClickListener = listener;
    }

}

ViewHolder仿照鸿洋大神的listView的holder

public class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {

    private SparseArray<View> mViews;
    private Context mContext;

    public BaseRecyclerViewHolder(Context context, View itemView) {
        super(itemView);
        this.mContext = context;
        mViews = new SparseArray<>();
    }

    private <T extends View> T findViewById(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getView(int viewId) {
        return findViewById(viewId);
    }
}

需要注意:

  1. 绑定数据源时的position,记得有几个header就减去几。参见:方法getRealPosition()
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值