RecyclerView
出来已经很久了。我对于之的使用,也仅限于当成ListView
orGridView
的使用。最近项目中有一个需求刚好需要用到多种item
的展示。我之前使用
RecyclerView
的adapter
全部使用的是hongyang/base-adapter。非常的方便。而且也提供多种item
的展示的功能。但是………我并没有找到正确的使用方式。于是这回就用到了原生的RecyclerView.Adapter
来实现多种itemType
。我的项目中,用到的是两种
item
。为了以后查找方便,就记录在这里了。
public class LockAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<LockInfo> dataList;
private final Context mContext;
private boolean canClick;
private int lockCount;
private int unLockCount;
private int mUnLockCountPos;
private int mLockCountPos;
public void setCanClick(boolean canClick) {
this.canClick = canClick;
notifyDataSetChanged();
}
public int getUnLockCountPos() {
return mUnLockCountPos;
}
public int getLockCount() {
return lockCount;
}
public int getUnLockCount() {
return unLockCount;
}
public LockAdapter(@NonNull Context context, @NonNull List<LockInfo> dataList) {
this.mContext = context;
this.dataList = dataList;
lockCount = Observable.fromIterable(dataList).filter(it -> it.locked)
.toList().blockingGet().size() - 1;
unLockCount = dataList.size() - 1 - (lockCount + 1);
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
// default item
View view = LayoutInflater.from(mContext)
.inflate(R.layout.item_app_list_layout, parent, false);
return new NormalVH(view);
} else if (viewType == 1) {
// first item
View view = LayoutInflater.from(mContext)
.inflate(R.layout.item_app_list_first_layout, parent, false);
return new FirstVH(view);
} else {
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
int adapterPosition = viewHolder.getAdapterPosition();
LockInfo info = dataList.get(adapterPosition);
if (viewHolder instanceof NormalVH) {
NormalVH holder = (NormalVH) viewHolder;
holder.ivIcon.setImageDrawable(info.appIcon);
holder.cbChecked.setChecked(info.locked);
holder.cbChecked.setEnabled(canClick);
holder.itemView.setEnabled(canClick);
holder.tvPackageName.setText(info.packageName);
if (canClick) {
holder.itemView.setOnClickListener(v -> {
info.locked = !info.locked;
if (info.locked) {
lockCount += 1;
unLockCount -= 1;
} else {
lockCount -= 1;
unLockCount += 1;
}
notifyItemChanged(adapterPosition);
notifyItemChanged(mLockCountPos);
notifyItemChanged(mUnLockCountPos);
EventBus.getDefault().post(new ChangeEvent(lockCount, unLockCount));
});
}
} else if (viewHolder instanceof FirstVH) {
FirstVH holder = (FirstVH) viewHolder;
if (info.locked) {
this.mLockCountPos = adapterPosition;
holder.tvFirst.setText(mContext.getString(R.string.has_locked_count, lockCount));
} else {
this.mUnLockCountPos = adapterPosition;
holder.tvFirst.setText(mContext.getString(R.string.un_locked_count, unLockCount));
}
}
}
@Override
public int getItemCount() {
return dataList.size();
}
private static class NormalVH extends RecyclerView.ViewHolder {
private final View itemView;
private final ImageView ivIcon;
private final TextView tvPackageName;
private final CheckBox cbChecked;
NormalVH(View itemView) {
super(itemView);
this.itemView = itemView;
ivIcon = (ImageView) itemView.findViewById(R.id.item_app_list_iv);
tvPackageName = (TextView) itemView.findViewById(R.id.item_app_list_tv_name);
cbChecked = (CheckBox) itemView.findViewById(R.id.item_app_list_cb);
}
}
private static class FirstVH extends RecyclerView.ViewHolder {
private final TextView tvFirst;
FirstVH(View itemView) {
super(itemView);
tvFirst = (TextView) itemView.findViewById(R.id.item_app_list_first_tv);
}
}
@Override
public int getItemViewType(int position) {
if (dataList.get(position).first) {
return 1;
} else {
return super.getItemViewType(position);
}
}
public void updateData(@NonNull List<LockInfo> update) {
this.dataList = update;
notifyDataSetChanged();
}
}
- 其实也是看到这篇文字之后,才知道怎么弄的。
强调一下,多个
itemType
时,需要注意的地方:Adapter
需要直接继承RecyclerView.Adapter<RecyclerView.ViewHolder>
,并且不要改变泛型类。- 重写
int getItemViewType(int position)
方法,第一种item
默认返回super.getItemViewType(position);
,也就是0,第二种item
再返回一个不同的值,我这里给的是1.(第三种,也是一样,我这里没有实现) - 有几种
item
就写几个RecyclerView.ViewHolder
,我这里是两个,于是我写了两个,分别是private static class NormalVH extends RecyclerView.ViewHolder{...}
和private static class FirstVH extends RecyclerView.ViewHolder {...}
这两个。 - 在
onCreateViewHolder()
方法中,分别判断当前用的是哪一种ViewHolder
,比如我这里:
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 0) { // default item View view = LayoutInflater.from(mContext) .inflate(R.layout.item_app_list_layout, parent, false); return new NormalVH(view); } else if (viewType == 1) { // first item View view = LayoutInflater.from(mContext) .inflate(R.layout.item_app_list_first_layout, parent, false); return new FirstVH(view); } else { return null; } }
- 在
onBindViewHolder()
方法中,也是一样,要根据不同的ViewHolder
做不同的绑定view
的操作。比如我这里:
@Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { int adapterPosition = viewHolder.getAdapterPosition(); LockInfo info = dataList.get(adapterPosition); if (viewHolder instanceof NormalVH) { NormalVH holder = (NormalVH) viewHolder; holder.ivIcon.setImageDrawable(info.appIcon); holder.cbChecked.setChecked(info.locked); holder.cbChecked.setEnabled(canClick); holder.itemView.setEnabled(canClick); holder.tvPackageName.setText(info.packageName); if (canClick) { holder.itemView.setOnClickListener(v -> { info.locked = !info.locked; if (info.locked) { lockCount += 1; unLockCount -= 1; } else { lockCount -= 1; unLockCount += 1; } notifyItemChanged(adapterPosition); notifyItemChanged(mLockCountPos); notifyItemChanged(mUnLockCountPos); EventBus.getDefault().post(new ChangeEvent(lockCount, unLockCount)); }); } } else if (viewHolder instanceof FirstVH) { FirstVH holder = (FirstVH) viewHolder; if (info.locked) { this.mLockCountPos = adapterPosition; holder.tvFirst.setText(mContext.getString(R.string.has_locked_count, lockCount)); } else { this.mUnLockCountPos = adapterPosition; holder.tvFirst.setText(mContext.getString(R.string.un_locked_count, unLockCount)); } } }
- 主要的需要注意的地方就是这几点了。
- 另外,这个代码如果直接拷过去是一定没有办法运行的。主要是讲一下实现过程。