Search code examples
androidandroid-recyclerviewandroid-viewholder

how to create one recycler view adapter for multiple viewholders that matches a viewholder of choice not in the same recycler view list


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

Solution

  • 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));
    }
    
    }