开篇
相信大家在项目的开发中都用到了QuickAdapter
,也感觉到了它确实提升了一些我们的开发效率。不仅仅你用了,我也用了,但是我还是觉得它还有很大的提升空间。为此,我特意抽时间封装了此RecyclerView
适配器。
效果截屏
SimpleAdapter.png
PullToRefreshRecyclerView
立即体验
扫描以下二维码下载体验App(体验App内嵌版本更新检测功能):
扫描下载体验App
传送门:https://github.com/JustinRoom/SimpleAdapterDemo
gradle引用
implementation 'jsc.kit.adapter:adapter-component:_latestVersion'
简析源码
public abstract class BaseHeaderFooterAdapter<H, D, F, E, VH extends BaseHeaderFooterAdapter.BaseViewHolder> extends RecyclerView.Adapter<VH> {}
1、封装了4中
ViewType
类型:H
——头(header)、D
——数据(data)、F
——尾(footer)、E
——空列表(empty)
/** * header 视图 */ public static final int TYPE_HEADER = 1000; /** * data 数据视图 */ public static final int TYPE_DATA = 1001; /** * footer 视图 */ public static final int TYPE_FOOTER = 1002; /** * 空列表视图 */ public static final int TYPE_EMPTY = 1003; private List<H> headers = new ArrayList<>(); private List<D> data = new ArrayList<>(); private List<F> footers = new ArrayList<>(); private List<E> empties = new ArrayList<>();
2、获取position位置的
ViewType
。
@Override public int getItemCount() { return getHeaderSize() + getInternalSize() + getFooterSize(); } @ViewType @Override public int getItemViewType(int position) { if (position >= getHeaderSize() + getInternalSize() + getFooterSize()) return UNKNOWN; if (position >= getHeaderSize() + getInternalSize()) return TYPE_FOOTER; if (position >= getHeaderSize()) return isEmptyData() ? TYPE_EMPTY : TYPE_DATA; if (position >= 0) return TYPE_HEADER; return UNKNOWN; } private int getInternalSize() { return isEmptyData() ? getEmptySize() : getDataSize(); }
3、封装
BaseViewHolder
,添加一些常用方法。public static class BaseViewHolder extends RecyclerView.ViewHolder {}
常用方法:public <V extends View> V findViewById(@IdRes int id)
public void setText(@IdRes int id, CharSequence txt)
public void setTextColor(@IdRes int id, @ColorInt int color)
public void setTextSize(@IdRes int id, float size)
public void setTextSize(@IdRes int id, int unit, float size)
public void setVisibility(@IdRes int id, int visibility)
public void setSelected(@IdRes int id, boolean selected)
public void setEnabled(@IdRes int id, boolean enable)
public void setBackgroundColor(@IdRes int id, @ColorInt int color)
public void setBackgroundResource(@IdRes int id, @DrawableRes int resId)
public void setBackground(@IdRes int id, Drawable background)
public void setTag(@IdRes int id, final Object tag)
public void setTag(@IdRes int id, int key, final Object tag)
void setPositionTag(int position)
void addOnItemClickListener(View.OnClickListener listener)
void addOnItemLongClickListener(View.OnLongClickListener listener)
void addOnChildClickListener(@IdRes int id, View.OnClickListener listener)
void addOnChildLongClickListener(@IdRes int id, View.OnLongClickListener listener)
4、绑定
View
。
@CallSuper @Override public void onBindViewHolder(@NonNull VH holder, int position) { holder.setPositionTag(position); holder.addOnItemClickListener(onItemClickListener == null ? null : getDefaultItemClickListener()); holder.addOnItemLongClickListener(onItemLongClickListener == null ? null : getDefaultItemLongClickListener()); switch (getItemViewType(position)) { case TYPE_HEADER: onBindHeaderViewHolder(holder, position, getHeaderAt(position)); break; case TYPE_DATA: onBindDataViewHolder(holder, position, getDataAt(position)); break; case TYPE_FOOTER: onBindFooterViewHolder(holder, position, getFooterAt(position)); break; case TYPE_EMPTY: onBindEmptyViewHolder(holder, position, getEmptyAt(position)); break; case UNKNOWN: break; } }
5、根据不同的
ViewType
创建不同View
视图:SimpleAdapter
。
public class SimpleAdapter<H, D, F, E> extends BaseHeaderFooterAdapter<H, D, F, E, BaseHeaderFooterAdapter.BaseViewHolder> { public SimpleAdapter() { } public SimpleAdapter(@LayoutRes int dataLayoutId) { super(dataLayoutId); } @NonNull @Override public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { switch (viewType) { case TYPE_HEADER: if (getHeaderLayoutId() == -1) throw new IllegalArgumentException(getClass().getSimpleName() + " : please set header layout first."); return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getHeaderLayoutId(), viewGroup, false)); case TYPE_DATA: if (getDataLayoutId() == -1) throw new IllegalArgumentException(getClass().getSimpleName() + " : please set footer layout first."); return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getDataLayoutId(), viewGroup, false)); case TYPE_FOOTER: if (getFooterLayoutId() == -1) throw new IllegalArgumentException(getClass().getSimpleName() + " : please set footer layout first."); return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getFooterLayoutId(), viewGroup, false)); case TYPE_EMPTY: return new BaseViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(getEmptyLayoutId() == -1 ? R.layout.recycler_default_empty_list_layout : getEmptyLayoutId(), viewGroup, false)); default: TextView textView = new TextView(viewGroup.getContext()); textView.setTextColor(Color.RED); textView.setGravity(Gravity.CENTER); textView.setText("Unknown view type"); textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new BaseViewHolder(textView); } } }
使用示例
1、简单使用示例:
RecyclerView recyclerView; adapter2 = new SimpleAdapter2<MaterielOrderDetail, MaterielDetail, Object>() { @Override protected void onBindHeaderViewHolder(@NonNull BaseViewHolder holder, int position, MaterielOrderDetail headerBean) { holder.setText(R.id.tv_company_name, formatValue("公司名称:", headerBean.getOrgName())); holder.setText(R.id.tv_type, formatValue("\u3000类型:", headerBean.getEventTypeName())); holder.setText(R.id.tv_warehouse_name, formatValue("仓库名称:", headerBean.getWarehouseName())); holder.setText(R.id.tv_partner_name, formatValue("供应商:", headerBean.getPartnerName())); if (headerBean.getCreateTime() > 0) { holder.setText(R.id.tv_create_time, formatValue("创建时间:", format.format(new Date(headerBean.getCreateTime())))); } else { holder.setText(R.id.tv_create_time, ""); } holder.setText(R.id.tv_creator, formatValue("创建人:", headerBean.getCreatePersonName())); //已经审核通过 if (MaterielMenu.orderStatus.get(2).getKey().equals(headerBean.getStatus())) { holder.setText(R.id.tv_auditing_time, formatValue("审核时间:", format.format(new Date(headerBean.getApproveTime())))); holder.setText(R.id.tv_auditor, formatValue("审核人:", headerBean.getApprovePersonName())); } else { holder.setText(R.id.tv_auditing_time, formatValue("审核时间:", "--")); holder.setText(R.id.tv_auditor, formatValue("审核人:", "--")); } holder.setText(R.id.tv_storage_type_label, String.format(Locale.CHINA, "%s物料:", opAction1 == IMateriel.OP_ACTION_IN ? "入库" : "出库")); } @Override protected void onBindDataViewHolder(@NonNull BaseViewHolder holder, int position, MaterielDetail dataBean) { holder.setText(R.id.tv_materiel_name, dataBean.getMaterialName()); if (dataBean.getBatchManage()) { holder.setText(R.id.tv_materiel_batch, String.format(Locale.CHINA, "(%s)", dataBean.getBatch())); } else { holder.setText(R.id.tv_materiel_batch, ""); } holder.setVisibility(R.id.btn_materiel_delete, View.GONE); holder.setText(R.id.tv_business_unit, formatValue("业务单位:", dataBean.getMultiUnitName())); holder.setText(R.id.tv_business_number, formatValue("业务数量:", String.valueOf(dataBean.getQuantity()))); holder.setText(R.id.tv_accounting_unit, formatValue("核算单位:", dataBean.getAccountUnitName())); holder.setText(R.id.tv_accounting_number, formatValue("核算数量:", String.valueOf(dataBean.getAccountQuantity()))); } SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd\u2000HH:mm", Locale.CHINA); CharSequence formatValue(String label, String value) { if (value == null || value.trim().length() == 0) { return label; } SpannableString spannableString = new SpannableString(label + value); spannableString.setSpan(new ForegroundColorSpan(0xFF90FFBE), label.length(), label.length() + value.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return spannableString; } }; adapter2.setHeaderLayoutId(R.layout.breed_fragment_materiel_detail_header); adapter2.setDataLayoutId(R.layout.breed_list_item_materiel); adapter2.bindRecyclerView(recyclerView); adapter2.addHeader(new MaterielOrderDetail());
2、各种事件监听:
2.1、
itemView
的点击事件监听:
public interface OnItemClickListener<H, D, F, E> { //每一条header的点击监听 void onHeaderItemClick(@NonNull View headerItemView, int position, H headerBean); //每一条data的点击监听 void onDataItemClick(@NonNull View dataItemView, int position, D dataBean); //每一条footer的点击监听 void onFooterItemClick(@NonNull View footerItemView, int position, F footerBean); //每一条empty的点击监听 void onEmptyItemClick(@NonNull View emptyItemView, int position, E emptyBean); }
2.2、
itemView
之child view
的点击事件监听
public interface OnItemChildClickListener<H, D, F, E> { //header child view点击监听 void onHeaderItemChildClick(@NonNull View headerChild, int position, H headerBean); //data child view点击监听 void onDataItemChildClick(@NonNull View dataItemChild, int position, D dataBean); //footer child view点击监听 void onFooterItemChildClick(@NonNull View footerChild, int position, F footerBean); //empty child view点击监听 void onEmptyItemChildClick(@NonNull View emptyChild, int position, E emptyBean); }
2.3、
itemView
的长按事件监听:
public interface OnItemLongClickListener<H, D, F, E> { //每一条header的长按监听 boolean onHeaderItemLongClick(@NonNull View headerItemView, int position, H headerBean); //每一条data的长按监听 boolean onDataItemLongClick(@NonNull View dataItemView, int position, D dataBean); //每一条footer的长按监听 boolean onFooterItemLongClick(@NonNull View footerItemView, int position, F footerBean); //每一条empty的长按监听 boolean onEmptyItemLongClick(@NonNull View emptyItemView, int position, E emptyBean); }
2.4、
itemView
之child view
的长按事件监听
public interface OnItemChildLongClickListener<H, D, F, E> { //header child view长按监听 boolean onHeaderItemChildLongClick(@NonNull View headerChild, int position, H headerBean); //data child view长按监听 boolean onDataItemChildLongClick(@NonNull View dataItemChild, int position, D dataBean); //footer child view长按监听 boolean onFooterItemChildLongClick(@NonNull View footerChild, int position, F footerBean); //empty child view长按监听 boolean onEmptyItemChildLongClick(@NonNull View emptyChild, int position, E emptyBean); }
使用介绍就到这里。
如果你觉得还不错的话,在GitHub上给一颗星星支持下吧。谢谢!如果在使用过程中不懂(或需要改进的地方),可以在评论里给我留言,也可以联系我。
作者:JustinRoom
链接:https://www.jianshu.com/p/23b8ef5c946b