Nested Android RecyclerView

How to create nested Android RecyclerView in Kotlin

manticarodrigo Android Leave a Comment

Oftentimes your app needs to dynamically create lists that also contain dynamic lists within parent list items. A good example of that is when an item list needs to be grouped by dates. This tutorial covers nesting a RecyclerView within a RecyclerView’s ViewHolder Adapter.

You can download the final project source code here.

Nested Android RecyclerView gif

Initial Setup

Start a new Android Studio project with an empty activity.

Place the following lines in your app build.gradle and run sync gradle files:

implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'

Next, you need to create all your resource files (layouts and drawables).

Drawables (optional)

Place circle_badge.xml in res/drawables. This part is purely aesthetic. If you skip this part, make sure to update your recyclerview_item_locations.xml file accordingly.

Layouts

Place the layout files in res/layout.

You’ll notice your activity_main.xml only contains one RecyclerView tag. That will be the parent RecyclerView and the nested ones will be created inside each list item in the Adapter’s ViewHolder. In recyclerview_item_dates.xml you’ll see the RecyclerView for each date item in the parent RecyclerView.

Now you need to update your MainActivity.kt file and create two Adapters, one for the parent RecyclerView and one for the child RecyclerViews.

Update your MainActivity.kt like so:

In MainActivity.kt you’ll see two custom functions, createMockData() and bindDataWithUi(). The first one creates the location objects with the properties we’ll be displaying in the lists. At the end, a call is made to the second function, passing the array of our newly created objects. The second function creates a LinearLayoutManager and assigns our MainAdapter.kt class as it’s adapter. Then, our Adapter classes handle the ViewHolder items in each RecyclerView level.

Create two new classes with the following content:

In MainAdapter.kt we are taking the locationList data as a parameter and using the locationList.groupBy { it["time"] } function to separate them by their dates. Then we reference the date and rv elements in the ViewHolder class. Assign the date label the correct value in a readable format in onBindViewHolder():

val sdf = SimpleDateFormat("MM/dd/yyyy")
val dateList = byDates.values.toMutableList()
holder.date?.text = sdf.format(dateList[position][0].get("time")?.toLong())

Also assign rv our other Adapter, MainLocationAdapter.kt and pass it the locations for the specific date using var adapter = MainTaskAdapter(dateList[position] as ArrayList>).

In MainTaskAdapter.kt you’ll receive that date’s locationList. Now all you need to do is get a reference to locationName and locationAddress in the ViewHolder class and assign their text values in onBindViewHolder() by getting the HashMap values for the list position using:

val location = locationList[position] holder.locationName?.text = location.get("name")
holder.locationAddress?.text = location.get("address")

Make sure your lists are rendering the proper itemCount:

override fun getItemCount(): Int {
return byDates.count()
}

override fun getItemCount(): Int {
return locationList.size
}

Now you’re ready to create your own dynamic nested RecyclerViews!

Leave a Reply

Your email address will not be published. Required fields are marked *