How to handle a lot of different view types in recyclerview viewholder

10,544

You can use only one viewHolder inner class to handle lots of different viewType. Firstly you have to use getItemViewType(viewType) to get the item position and also have to use viewHolder according to viewType Position.

Make One vieHolder inner class in which you can pass view and viewtype according to position of item and inflate the layout as shown below code. Code sample is given below.

public class Adapter extends
        RecyclerView.Adapter<Adapter.MyViewholder> {

LayoutInflater inflater;
private Context context;
ArrayList<Detail> data = new ArrayList<Detail>();

public Adapter(Context context, ArrayList<Detail> getdata) {
    this.context = context;
    inflater = LayoutInflater.from(context);
    this.data = getdata;
}

class MyViewholder extends RecyclerView.ViewHolder {
    TextView txtRow, txt_rec;

    public MyViewholder(View view, int type) {
        super(view);

        if (type == Constants.NORMAL) {
            txtRow = (TextView) view
                    .findViewById(R.id.txtRow);
        } else if (type == Constants.RECORDING) {
            txt_rec = (TextView) view
                    .findViewById(R.id.txt_rec);
        } 
    }
}

@Override
public int getItemCount() {
    return data.size();
}

@Override
public void onBindViewHolder(MyViewholder viewholder, int position) {
    int listViewItemType = getItemViewType(position);
    Detail detail = data.get(listViewItemType);
    if (detail.getType() == Constants.NORMAL) {
        viewholder.txtRow.setText(detail.getKey());
    } else if (detail.getType() == Constants.RECORDING) {
        viewholder.txt_rec.setText(detail.getRecording());
    } 

}

@Override
public MyViewholder onCreateViewHolder(ViewGroup parent, int viewType) {

    int listViewItemType = getItemViewType(viewType);
  switch (listViewItemType) {
         case 0: 
              view = inflater.inflate(R.layout.detail_item, parent,
                    false);
            myViewholder = new MyViewholder(view, Constants.NORMAL);
         case 2: 
             view = inflater.inflate(R.layout.recording, parent, false);
            myViewholder = new MyViewholder(view, Constants.RECORDING);
    }
    return myViewholder;
}

@Override
public int getItemViewType(int position) {
        return position;
    }
}

Hope this code will help you

Share:
10,544
Tamas
Author by

Tamas

Updated on June 04, 2022

Comments

  • Tamas
    Tamas about 2 years

    What if I have 50 types of views? Should I have 50 static inner classes in my adapter? According to this answer, yes.

    My first thought was to move each viewholder inner class into a seperate public class, but they have to be static. So encapsulate each one into a public class, to make the inner class static? Are there any nicer alternatives?

    edit: code sample: So this would be a good solution? Doesn't this also kill performance?

    public class MainViewHolder extends DragSortAdapter.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
    View container;
    TextView title;
    
    //called in onCreateViewHolder in adapter
    public MainViewHolder(DragSortAdapter adapter, View itemView) {
        super(adapter, itemView);
    
        container = itemView.findViewById(R.id.card_root);
    
        title = container.findViewById(R.id.text);
    }
    //called by onBindViewHolder in adapter
    public void setData(Data data) {
        title.setText(data.title);
    }
    }
    

    edit2: sample, for when a new instance is returned of the viewholder

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         switch (viewType) {
             case 0: return new MainViewHolder(...);
             case 2: return new MainViewHolderOther(...);
             ...
         }
    }