问题
I would like to know how I can create ONE recycler view adapter that holds MULTIPLE view-holders and each time the RecyclerView is instantiated with that adapter,I want to see only a specific type rather than a mixed type.
I have 2 different screens in the Android activity and each of them shows a list of items/cards.One is of text and number and the other is a photo. Right now I have 2 different custom adapters for each object and what I want to achieve is the flexibility of one adapter that can defer between the types of objects according to the screen its displaying and list only the rows I need.
All the examples I've seen are of mixed type objects and it is not what I am after.
The Adapter code is appended below.
public class MultiAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<MYDataProvider> arrayList;
private final static int VIEW0 = 0;
private final static int VIEW1 = 1;
public MultiAdapter(ArrayList<MyDataProvider> _arrayList) {
this.arrayList = new ArrayList<>();
this.arrayList = _arrayList;
}
@Override
public int getItemViewType(int position) {
switch (position) {
case 0:
return VIEW0;
case 1:
default:
return VIEW1;
}//switch
}//get item view type
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
int layoutRes;
View view;
RecyclerView.ViewHolder viewholder;
switch (viewType) {
case VIEW0:
layoutRes = R.layout.card_item;
view = LayoutInflater.from(viewGroup.getContext()).inflate(layoutRes, viewGroup, false);
viewholder = new E1(view);
break;
case VIEW1:
default:
layoutRes = R.layout.item_layout;
view = LayoutInflater.from(viewGroup.getContext()).inflate(layoutRes, viewGroup, false);
viewholder = new E2(view);
break;
}//switch
return viewholder;
}//on create
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case VIEW0: {
MyDataProvider mydata = arrayList.get(position);
((E1)holder).name1.setText(mydata.getD_name() + "this is item " + position);
((E1)holder).imageView1.setImageResource(arrayList.get(position).getImg_res());
}
break;
case VIEW1: {
MyDataProvider mydata = arrayList.get(position);
((E2)holder).name2.setText(mydata.getD_name() + "this is item " + position);
((E2)holder).imageView2.setImageResource(arrayList.get(position).getImg_res());
}
break;
}//switch
}//on bind
@Override
public int getItemCount() {
return arrayList.size();
}
public class E1 extends mainViewHolder {
ImageView imageView1;
TextView name1;
public E1(View itemView) {
super(itemView);
imageView1 = itemView.findViewById(R.id.image);
name1 = itemView.findViewById(R.id.d_name);
}
}//e1 class
public class E2 extends mainViewHolder {
ImageView imageView2;
TextView name2;
public E2(View itemView) {
super(itemView);
imageView2 = itemView.findViewById(R.id.person_photo);
name2 = itemView.findViewById(R.id.person_name);
}
}//e2 class
public class mainViewHolder extends RecyclerView.ViewHolder {
public mainViewHolder(@NonNull View itemView) {
super(itemView);
}
}
}//adapter
回答1:
I don't get it where is your problem? Can you provide more explanation what you want to achieve?
// edit
In your code you determine that only first item will be item of type VIEW0 and others will be VIEW1. This is in getItemViewType(int position)
function.
If you want determine what ViewHolder to pick you must to choose it before you populate list. Create enum in your adapter:
enum TYPE {
VIEW0,
VIEW1
}
then create variable of enum:
private TYPE itemType;
and pass it in your constructor:
public Test(ArrayList<MyDataProvider> _arrayList, TYPE itemType) {
this.arrayList = new ArrayList<>();
this.arrayList = _arrayList;
this.itemType = itemType;
}
and check what is your type (based on itemType
variable) in your switch in onCreateViewHolder
function like that. Note that variable in switch is "itemType", not viewType from override method.
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (itemType) {
case VIEW0:
return new NotificationsAdapter.ReferralTriggerViewHolder(inflater.inflate(R.layout.row_referral_trigger, parent, false));
case VIEW1:
return new NotificationsAdapter.UserNotificationViewHolder(inflater.inflate(R.layout.row_layout_user_notification, parent, false));
default:
return new NotificationsAdapter.UserNotificationViewHolder(inflater.inflate(R.layout.row_layout_user_notification, parent, false));
}
}
回答2:
public class NotificationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_REFERRAL_TRIGGER = 1;
private static final int VIEW_TYPE_NOTIFICATION = 2;
private static final int VIEW_TYPE_PROMOTION = 3;
private List<Object> notificationObjectsList;
private Activity mActivity;
public NotificationsAdapter(Activity activity, List<Object> mNotificationList) {
mActivity = activity;
notificationObjectsList = new ArrayList<>(mNotificationList);
}
// Used to avoid the duplicate items recycling
@Override
public long getItemId(int position) {
return position;
}
// Used to avoid the duplicate items recycling
@Override
public int getItemViewType(int position) {
if ((notificationObjectsList.get(position) != null) && (notificationObjectsList.get(position) instanceof ReferralData)) {
return VIEW_TYPE_REFERRAL_TRIGGER;
} else if (notificationObjectsList.get(position) instanceof Promotion) {
return VIEW_TYPE_PROMOTION;
} else {
return VIEW_TYPE_NOTIFICATION;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case VIEW_TYPE_REFERRAL_TRIGGER:
return new NotificationsAdapter.ReferralTriggerViewHolder(inflater.inflate(R.layout.row_referral_trigger, parent, false));
case VIEW_TYPE_NOTIFICATION:
return new NotificationsAdapter.UserNotificationViewHolder(inflater.inflate(R.layout.row_layout_user_notification, parent, false));
case VIEW_TYPE_PROMOTION:
return new NotificationsAdapter.PromotionViewHolder(inflater.inflate(R.layout.row_layout_app_promotions, parent, false));
default:
return new NotificationsAdapter.UserNotificationViewHolder(inflater.inflate(R.layout.row_layout_user_notification, parent, false));
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
if (viewHolder instanceof PromotionViewHolder) {
final PromotionViewHolder promotionViewHolder = (PromotionViewHolder) viewHolder;
//populate data of promotion view holder
} else if (viewHolder instanceof UserNotificationViewHolder) {
final UserNotificationViewHolder notificationViewHolder = (UserNotificationViewHolder) viewHolder;
//populate data of UserNotificationViewHolder view holder
} else if (viewHolder instanceof ReferralTriggerViewHolder) {
final ReferralTriggerViewHolder referralTriggerViewHolder = (ReferralTriggerViewHolder) viewHolder;
//populate data of ReferralTriggerViewHolder view holder
}
}
@Override
public int getItemCount() {
return notificationObjectsList.size();
}
private class UserNotificationViewHolder extends RecyclerView.ViewHolder {
private UserNotificationViewHolder(View itemView) {
super(itemView);
}
}
private class PromotionViewHolder extends RecyclerView.ViewHolder {
private PromotionViewHolder(View itemView) {
super(itemView);
}
}
private class ReferralTriggerViewHolder extends RecyclerView.ViewHolder {
ReferralTriggerView referralTriggerView;
private ReferralTriggerViewHolder(View itemView) {
super(itemView);
referralTriggerView = itemView.findViewById(R.id.rtv_notification_adapter);
}
}
}
来源:https://stackoverflow.com/questions/51191230/how-to-create-one-recycler-view-adapter-for-multiple-viewholders-that-matches-a