一、需求分析
当我们使用RecyclerView的时候,基本都需要写一个适配器继承RecyclerAdapter,其中有很多需要重写的方法,并且这部分代码也都是重复的,还有ViewHolder的重用代码,每次都要写一遍的话很繁琐,所以我们可以把这部分代码全部封装出来,然后子类只需要处理关键性的代码就行。
二、功能
- item 的点击事件回调
- item 的长按时间回调
- ViewHolder 的封装
- 大量重复的父类方法实现,子类不再需要实现它们不同的部分代码
三、代码
下面代码封装了RecyclerAdapter,同时有一个通用性的ViewHolder,这个ViewHolder类也可以作为一个公用的类来使用。
代码里面添加了一个item的点击事件回调,还有一个item的长按事件回调。
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public abstract class MyRecyclerAdapter<T> extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {
protected Context mContext;
protected int mLayoutId;
protected List<T> mList;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
public MyRecyclerAdapter() {}
public MyRecyclerAdapter(Context context, List<T> list, int layoutId) {
mContext = context;
mList = list;
mLayoutId = layoutId;
}
@Override
public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
ViewHolder viewHolder = ViewHolder.getInstance(mContext, mLayoutId, parent);
return viewHolder;
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if (mList.size() > 0)
convert(holder, mList.get(position), position);
if (mOnItemClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = holder.getLayoutPosition();
mOnItemClickListener.onItemClick(holder.itemView, position);
}
});
}
if (mOnItemLongClickListener != null) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int position = holder.getLayoutPosition();
mOnItemLongClickListener.onItemLongClick(holder.itemView, position);
return true; // 返回true 表示消耗了事件 事件不会继续传递
}
});
}
}
public abstract void convert(ViewHolder holder, T t, int position);
@Override
public int getItemCount() {
return mList.size();
}
public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
this.mOnItemClickListener = mOnItemClickListener;
}
public void setOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
this.mOnItemLongClickListener = mOnItemLongClickListener;
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public interface OnItemLongClickListener {
void onItemLongClick(View view, int position);
}
protected static class ViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews;
private View mConvertView;
public ViewHolder(View itemView) {
super(itemView);
mConvertView = itemView;
mViews = new SparseArray<>();
}
public static ViewHolder getInstance(Context context, int layoutId, ViewGroup parent) {
View itemView = LayoutInflater.from(context).inflate(layoutId, parent, false);
ViewHolder holder = new ViewHolder(itemView);
return holder;
}
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
}
}
四、实例
下面这个实例是一个存在多个 type 的实例
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.afei.R;
import com.afei.bean.TargetLibWrapper;
import java.util.List;
public class TargetLibCollapseAdapter extends MyRecyclerAdapter<TargetLibWrapper> {
private static final int TYPE_CATEGORY = 0;
private static final int TYPE_ITEM = 1;
private int categoryLayoutId;
private int itemLayoutId;
private int mDividePos;
public TargetLibCollapseAdapter(Context context, List<TargetLibWrapper> list) {
mContext = context;
mList = list;
categoryLayoutId = R.layout.target_lib_category_layout;
itemLayoutId = R.layout.target_lib_item_collapse_layout;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewHolder holder;
if (viewType == TYPE_CATEGORY) {
holder = ViewHolder.getInstance(mContext, categoryLayoutId, parent);
} else {
holder = ViewHolder.getInstance(mContext, itemLayoutId, parent);
}
return holder;
}
@Override
public void convert(ViewHolder holder, TargetLibWrapper wrapper, final int position) {
if (getItemViewType(position) == TYPE_CATEGORY) {
ImageView searchIv = holder.getView(R.id.is_search_iv);
TextView searchTv = holder.getView(R.id.is_search_tv);
searchIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_search_true : R.mipmap.ic_search_false);
int color = wrapper.isSearch() ? mContext.getResources().getColor(R.color.targetLibItemChecked) : Color
.BLACK;
searchTv.setTextColor(color);
searchTv.setText(wrapper.getCategoryName());
} else {
ImageView statusIv = holder.getView(R.id.target_lib_status_iv);
ImageView folderIv = holder.getView(R.id.target_lib_folder_iv);
TextView nameTv = holder.getView(R.id.target_lib_name_tv);
statusIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_delete : R.mipmap.ic_add);
folderIv.setImageResource(wrapper.isSearch() ? R.mipmap.ic_folder_checked : R.mipmap.ic_folder_unchecked);
nameTv.setText(wrapper.getTargetLibEntity().getName());
statusIv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
move(position);
}
});
}
}
@Override
public int getItemViewType(int position) {
if (mList.get(position).isCategory()) {
if (position != 0) {
mDividePos = position;
}
return TYPE_CATEGORY;
}
return TYPE_ITEM;
}
private void move(int position) {
TargetLibWrapper targetLib = mList.get(position);
if (targetLib.isSearch()) {
targetLib.setSearch(false);
mList.remove(position);
mList.add(mDividePos, targetLib);
} else {
targetLib.setSearch(true);
mList.remove(position);
mList.add(1, targetLib);
}
notifyDataSetChanged();
}
}