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<T> {
    void onItemLongClick(View view, T t, int position);
}

OnRecyclerViewItemClickListener:

public interface OnRecyclerViewItemClickListener<T> {
    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<T> extends RecyclerView.Adapter<BaseRecyclerHolder> implements View.OnClickListener, View.OnLongClickListener {

    private List<T> mDatas = new ArrayList<>();
    protected OnRecyclerViewItemClickListener<T> mOnItemClickListener;
    protected OnRecyclerViewItemLongClickListener<T> 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<T> 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<T> getDatas() {
        return mDatas;
    }


    // 事件相關
    public void setOnItemClickListener(OnRecyclerViewItemClickListener<T> listener) {
        this.mOnItemClickListener = listener;
    }

    public void setOnItemLongClickListener(OnRecyclerViewItemLongClickListener<T> 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<ImageBean> 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<ImageBean>() {
            @Override
            public void onItemLongClick(View view, ImageBean bean, int position) {

            }
        });

使用click事件類似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章