现在我们基本上不怎么使用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事件类似。