Manish Khandelwal
Manish Khandelwal

Reputation: 33

Adding multiple views to a Recycler View dynamically

I am creating a chatting application where in I need to populate a different Xml file based on the messageType in the chats page where all the conversation with a particular user is displayed. Example if the messageType is an image I want to populate a different xml and if the messageType is a video I want to populate a different xml file, and similarly for a text and audio a different xml file each time. However in my code, I have populated a single common xml in the onCreateViewHolder method. The messageType is retrieved from the model class.

Any help how to do this ?

Thanks in advance !!

Upvotes: 0

Views: 652

Answers (2)

Ben P.
Ben P.

Reputation: 54194

You can do this by using different "item view type" values for each messageType. The root of this logic is the adapter's getItemViewType() callback:

@Override
public int getItemViewType(int position) {
    if (isImage(position)) {
        return R.layout.layout_for_image;
    } else if (isVideo(position) {
        return R.layout.layout_for_video;
    } else {
        // and so on...
    }
}

We're using a trick here: getItemViewType() only cares that you return an int; it doesn't care what the actual int values are, so we're using the layout ids as the return value. This is nice because it means you don't have to define extra constants or keep track of which view type goes with 0 and which goes with 1, etc.

You also need to create a different kind of ViewHolder for each view type. The viewType parameter passed to this method will have whatever value you returned from getItemViewType(), and since we returned layout ids, we can just inflate whatever value we get. Of course, we still have to pass it to the right ViewHolder, but still it makes things a little easier:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View itemView = inflater.inflate(viewType, parent, false);

    switch (viewType) {
        case R.layout.layout_for_image: return new ImageViewHolder(itemView);
        case R.layout.layout_for_video: return new VideoViewHolder(itemView);
        ...
    }
}

The last piece is binding:

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
    switch (holder.getItemViewType()) {
        case R.layout.layout_for_image:
            bindImage(holder, position);
            break;

        case R.layout.layout_for_video:
            bindVideo(holder, position);
            break;

        ...
    }
}

Upvotes: 1

Marcos Vasconcelos
Marcos Vasconcelos

Reputation: 18276

Override getViewType(int index) and return different values for object types, then you get it at onCreateViewHolder and inflate the correct view with different ViewHolders, the same type of viewholder will be returned at onBindViewHolder for equals viewTypes.

Upvotes: 0

Related Questions