👨🏼‍💻 RecyclerView Multiple View Types

Sertaç Ayhan
Huawei Developers
Published in
5 min readJun 3, 2022
# Image Source

Introduction

Hi folks! In this article, I will try to give you the answer to the question of how to solve a real problem by using RecyclerView with different view types. Enjoy :)

The problem : I have a list of <PhotoModel> which contains photo’s path, coordinate etc. I want to see photos grouped by date.

As you already know RecyclerView structure creates a list that includes similar items. This time, however, we will create a completely different type of a list which consists of more than one type of item. I will create a layout which contains a TextView to display date value and an ImageView to display images. Let’s get started.

Layouts

Fragment.xml

fragment.xml

date_item.xml that will display date value

date_item.xml

gallery_item.xml that will display photos

gallery_item.xml

RecyclerView Item Data Class

We use sealed class to be able to hold RecyclerView data.

RecyclerView Adapter

We wrote a code similar to ordinary RecyclerViewAdapter, here is the extra
getItemViewType() function . With this function, we check the type of the item coming from the layout id.

inside onCreateViewHolder() according to the incoming ViewType, we are generating a ViewHolder instance.

We check the holder’s type in onBindViewHolder() and bind the data with ViewHolder accordingly.

RecyclerView ViewHolders

Usually we make only a single ViewHolder, but this time we are building a complex list and we need multiple ViewHolders. Each ViewHolder will hold a specific View that is needed for our list.

I have created a sealed ViewHolder class and then all of my ViewHolder (in this case 2) classes are defined using the same sealed ViewHolder class. Using sealed class will help us to make sure that these are only the options available for the ViewHolder. And if you need more types of Views then you can add more ViewHolder implementations inside this sealed class.

We also have a bind function inside each ViewHolder implementation, that will bind the given item with the View.

ViewModel

PhotoModel

Before moving onto ViewModel, I will briefly mention PhotoModel.

PhotoModel

This PhotoModel class is a data class we hold data of our photos. As you can see, it holds path and coordinate variables and ClusterItem. This ClusterItem is an interface of the library itself providing getLatitude and getLongtitude skills. As we will use path value here, I will not go into more detail. You can check out the link below to learn more on library. :)

We have a list which contains Photomodels. I have this list passed to ClusteredPhotosFragment from HomeFragment via parcelable.

Now, we will move onto ViewModel. First, I created a mutable list, named items, that holds data ClusteredPhotosViewItem type. This list will allow us to hold returned photo list by grouping by date.

In order to do this, I created setClusteredItems function in ViewModel,having photolist parameter Array<PhotoModel> and having contentResolver parameter ContentResolver. This function first assigns to date variable of ClusteredPhotosViewItem by using photo path via groupBy.

Then, we assign path variable of each photo that has that date to image variable of ClusteredPhotosViewItem, the type of items list, by using forEach.

Next, we change this date to desired format with an extension function. Then, we assign that date to the date section in items list with forEach. Then, we assign path variable of each photo that has that date to image variable of ClusteredPhotosViewItem, the type of items list, by using forEach.

In this way, our photos are grouped by the date. :)

ViewModel

getDateInfoFromPhoto function, as the name suggested, allows us to get data from a photo. Exif interface makes this possible. If you don’t know displaying photos in phone memory and how to get location data of photos, you can take a look at this article of my teammate. In this article, you can find the answer to the question how to use Exif interface, as well. :)

getFormattedDate function allows us to convert returned date format to the desired one, again as the name suggested.

Creating RecyclerView

We have a list which contains PhotoModels. I have this list passed to ClusteredPhotosFragment from HomeFragment via parcelable.

Then, we gave this list as a parameter to setClusteredItems created in viewModel inside setupUi function.

setupUi function is called in onViewCreated() created in BaseFragment. We use it by overriding as we created it in base. That is, you can consider this as used directly inside onViewCreated.

In order to display the date in order and the photos of that particular date, we use the structure of GridLayoutManager together SpanSizeLookup with getSpanSize function.

This function returns the number of span occupied by the item at position. I wanted single date view and photos to be displayed in groups of four. (Dates to be viewed individually)

The reason why I assigned 4 to date_item and 1 to gallery_item is that this structure has reverse logic.

Finally, we indicate LayoutManager by defining RecyclerView. We link our Adapter to the list and match RecyclerView with Adapter.

Result

Finally we are able to see photos grouped by date :)

--

--