RecyclerView的全能适配器,带有header和bottom

概述

现在我们基本上不怎么使用ListView,而是使用RecyclerView代替了,关于如何引入和基本使用RecyclerView这里就不分享了,我们主要分享的是如何打造一个全能的适配器给RecyclerView使用。
本文的例子是一个可以添加头部和底部的RecyclerView,我们将在BaseAdapter去处理。

思路

1,我们需要一个BaseRecyclerAdapter去继承RecyclerView.Adapter
2,我们需要一个BaseRecyclerHolder去继承RecyclerView.ViewHolder
3,我们有三种类型的ViewType,一个是header,一种是正常的itemView,一种是bottom
4,我们需要自己集成onClick和onLongClick两种事件

实现

1,对于BaseRecyclerHolder,我们具体的ViewHolder使用一个简单的注入框架来实现View的初始化,所以我们在BaseRecyclerHolder引入,具体代码如下:

public abstract class BaseRecyclerHolder extends RecyclerView.ViewHolder {
    public View itemView;
    public BaseRecyclerHolder(View itemView) {
        super(itemView);
        this.itemView = itemView;
        ButterKnife.bind(this, itemView);
    }
}

需要注意的是他需要声明为一个独立的java文件,不能作为BaseRecyclerAdapter的内部类
对于onClick和onLongClick事件,我们使用泛型去实现具体的回调数据,具体代码,他们二者比较类似
OnRecyclerViewItemLongClickListener:

public interface OnRecyclerViewItemLongClickListener {
    void onItemLongClick(View view, T t, int position);
}

OnRecyclerViewItemClickListener:

public interface OnRecyclerViewItemClickListener {
    void onItemClick(View view, T t, int position);
}

对于BaseRecyclerAdapter,我们需要重写RecyclerView.Adapter的一些方法,首先是onCreateViewHolder方法,我们在这里判断需要创建的Holder的类型,一共三种,一种是header的一种是bottom的,一种是itemView的,具体代码:

 @Override
    public final BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemtView;
        if (viewType == ITEM_TYPE_HEADER) {
            itemtView = LayoutInflater.from(App.me()).inflate(getHeaderLayout(), parent, false);
            return getBottomHolder(itemtView);
        } else if (viewType == ITEM_TYPE_BOTTOM) {
            itemtView = LayoutInflater.from(App.me()).inflate(getBottomLayout(), parent, false);
            return getHeaderHolder(itemtView);
        } else if (viewType == ITEM_TYPE_CONTENT) {
            itemtView = LayoutInflater.from(App.me()).inflate(getItemLayout(), parent, false);
            return getHolder(itemtView);
        }
        return null;

    }

使用final是不需要子类去重写这个方法。
然后,我们需要在onBindViewHolder方法绑定数据的时候判断是属于哪一种ViewHolder,然后做不同的处理。具体代码

   public final void onBindViewHolder(BaseRecyclerHolder holder, int position) {
        if (isBottomView(position)) {
            converBottomHolderView(holder);
        } else if (isHeaderView(position)) {
            converHeaderHolderView(holder);
        } else {
            // 需要注意获取数据时候开始的位置,需要减去头部占据的size
            holder.itemView.setTag(position-mHeaderCount);
            holder.itemView.setOnClickListener(this);
            holder.itemView.setOnLongClickListener(this);
            converHolderView(holder, mDatas.get(position-mHeaderCount), position-mHeaderCount);
        }
    }

这里需要注意的一个点是我们的itemView的数据计算,他是需要减去header的数量之后才是正确的。
完整代码:
BaseRecyclerAdapter:

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

import com.liweijie.design.graduation.gallery.app.App;
import com.liweijie.design.graduation.gallery.event.OnRecyclerViewItemClickListener;
import com.liweijie.design.graduation.gallery.event.OnRecyclerViewItemLongClickListener;
import com.liweijie.design.graduation.gallery.util.L;

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


/**
 * Created by liweijie on 2016/3/28.
 *
 */
public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter implements View.OnClickListener, View.OnLongClickListener {

    private List mDatas = new ArrayList<>();
    protected OnRecyclerViewItemClickListener mOnItemClickListener;
    protected OnRecyclerViewItemLongClickListener mOnItemLongClickListener;

    private int mHeaderCount ;//头部View个数
    private int mBottomCount ;//底部View个数

    //三种类型
    public static final int ITEM_TYPE_HEADER = 0;
    public static final int ITEM_TYPE_CONTENT = 1;
    public static final int ITEM_TYPE_BOTTOM = 2;


    public BaseRecyclerAdapter(List mDatas, int mHeaderCount, int mBottomCount) {
        this.mDatas.addAll(mDatas);
        this.mHeaderCount = mHeaderCount;
        this.mBottomCount = mBottomCount;
    }

    @Override
    public final BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemtView;
        if (viewType == ITEM_TYPE_HEADER) {
            itemtView = LayoutInflater.from(App.me()).inflate(getHeaderLayout(), parent, false);
            return getBottomHolder(itemtView);
        } else if (viewType == ITEM_TYPE_BOTTOM) {
            itemtView = LayoutInflater.from(App.me()).inflate(getBottomLayout(), parent, false);
            return getHeaderHolder(itemtView);
        } else if (viewType == ITEM_TYPE_CONTENT) {
            itemtView = LayoutInflater.from(App.me()).inflate(getItemLayout(), parent, false);
            return getHolder(itemtView);
        }
        return null;

    }


    /**
     *
     * @param holder
     * @param position
     */
    @Override
    public final void onBindViewHolder(BaseRecyclerHolder holder, int position) {
        if (isBottomView(position)) {
            converBottomHolderView(holder);
        } else if (isHeaderView(position)) {
            converHeaderHolderView(holder);
        } else {
            // 需要注意获取数据时候开始的位置,需要减去头部占据的size
            holder.itemView.setTag(position-mHeaderCount);
            holder.itemView.setOnClickListener(this);
            holder.itemView.setOnLongClickListener(this);
            converHolderView(holder, mDatas.get(position-mHeaderCount), position-mHeaderCount);
        }
    }

    @Override
    public int getItemCount() {
        return mDatas.size() + mHeaderCount + mBottomCount;
    }

    public int getContentCount() {
        return mDatas.size();
    }

    //判断当前item是否是HeadView
    public boolean isHeaderView(int position) {
        return mHeaderCount != 0 && position < mHeaderCount;
    }

    //判断当前item是否是FooterView
    public boolean isBottomView(int position) {
        L.i("Bottom",position+"==" +(mHeaderCount+getContentCount()));
        return mBottomCount != 0 && position >= (mHeaderCount + getContentCount());
    }

    @Override
    public int getItemViewType(int position) {
        int dataItemCount = getContentCount();
        // 第一个
        if (mHeaderCount != 0 && position < mHeaderCount) {
            //头部View
            return ITEM_TYPE_HEADER;
        } else if (mBottomCount != 0 && position >= (mHeaderCount + dataItemCount)) { //底部
            //底部View
            return ITEM_TYPE_BOTTOM;
        } else {
            //内容View
            return ITEM_TYPE_CONTENT;
        }
    }


    public abstract BaseRecyclerHolder getHolder(View itemtView);

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public BaseRecyclerHolder getBottomHolder(View itemtView) {
        return null;
    }

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public BaseRecyclerHolder getHeaderHolder(View itemtView) {
        return null;
    }

    public abstract int getItemLayout();

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public int getHeaderLayout() {
        return 0;
    }

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public int getBottomLayout() {
        return 0;
    }

    public abstract void converHolderView(BaseRecyclerHolder holder, T t, int position);

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public void converBottomHolderView(BaseRecyclerHolder holder) {

    }

    /**
     * 子类需要,子类实现
     *
     * @return
     */
    public void converHeaderHolderView(BaseRecyclerHolder holder) {

    }


    // 一般操作
    public void add(T t) {
        mDatas.add(t);
        this.notifyDataSetChanged();
    }


    public T get(int position) {
        return mDatas.size() <= position ? mDatas.get(position) : null;
    }

    public List getDatas() {
        return mDatas;
    }


    // 事件相关
    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }

    public void setOnItemLongClickListener(OnRecyclerViewItemLongClickListener listener) {
        this.mOnItemLongClickListener = listener;
    }

    // 事件

    @Override
    public void onClick(View v) {
        if (mOnItemClickListener != null) {
            int position = (int) v.getTag();
            mOnItemClickListener.onItemClick(v, mDatas.get(position), position);
        }
    }

    @Override
    public boolean onLongClick(View v) {
        if (mOnItemLongClickListener != null) {
            int position = (int) v.getTag();
            mOnItemLongClickListener.onItemLongClick(v, mDatas.get(position), position);
        }
        return false;
    }


}

这样子,我们通过抽闲方法让子类实现,通过一些header或者是bottom的方法,让子类选择实现,避免无用代码。
使用:

public class CollectFragmentAdapter extends BaseRecyclerAdapter<ImageBean> {

    public CollectFragmentAdapter(List mDatas) {
        super(mDatas, 1, 1);
    }

    @Override
    public BaseRecyclerHolder getHolder(View itemtView) {
        return new CollectHolder(itemtView);
    }

    @Override
    public int getItemLayout() {
        return R.layout.item_gallery_all_pic;
    }

    @Override
    public int getHeaderLayout() {
        return R.layout.core_blank_view;
    }

    @Override
    public int getBottomLayout() {
        return R.layout.core_blank_view;
    }

    @Override
    public BaseRecyclerHolder getBottomHolder(View itemtView) {
        return new CollectBottomHolder(itemtView);
    }

    @Override
    public BaseRecyclerHolder getHeaderHolder(View itemtView) {
        return new CollectHeaderHolder(itemtView);
    }

    @Override
    public void converHolderView(BaseRecyclerHolder holder, ImageBean imageBean, int position) {
        if (holder instanceof CollectHolder) {
            CollectHolder localHolder = (CollectHolder) holder;
            localHolder.collect_item_tv_cont.setText(String.valueOf(imageBean.getCount()));
            localHolder.collect_item_tv_name.setText("" + imageBean.getName());
            MyImageLoader.getInstance(2, MyImageLoader.Type.LIFO).loadImage(imageBean.getFirstImage(), localHolder.collect_item_iv_first);
        }
    }

    class CollectHolder extends BaseRecyclerHolder {
        @Bind(R.id.collect_item_iv_first)
        ImageView collect_item_iv_first;
        @Bind(R.id.collect_item_tv_name)
        TextView collect_item_tv_name;
        @Bind(R.id.collect_item_tv_cont)
        TextView collect_item_tv_cont;

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

    class CollectHeaderHolder extends BaseRecyclerHolder {
        public CollectHeaderHolder(View itemView) {
            super(itemView);
        }
    }

    class CollectBottomHolder extends BaseRecyclerHolder {
        public CollectBottomHolder(View itemView) {
            super(itemView);
        }
    }
}

这样子就行了,以后我们的Adapter就可以继承这个BaseRecyclerAdapter了。
使用longclock事件:

mAdapter.setOnItemLongClickListener(new OnRecyclerViewItemLongClickListener() {
            @Override
            public void onItemLongClick(View view, ImageBean bean, int position) {

            }
        });

使用click事件类似。

你可能感兴趣的:(Android基础相关)