Android Tutorial

Software Setup and Configuration

Android Studio

File Structure

Components

Core Topics

Layout

View

Button

Intent and Intent Filters

Toast

RecyclerView

Fragments

Adapters

Other UI Component

Image Loading Libraries

Date and Time

Material Design

Bars

Working with Google Maps

Chart

Animation

Database

Advance Android

Jetpack

Architecture

App Publish

App Monetization

How to create a nested RecyclerView in Android

A nested RecyclerView typically refers to having a RecyclerView inside another RecyclerView's item. This pattern is common for use cases like:

  • Horizontal lists within vertical lists: Think of the Google Play Store app where you have a vertical list of categories (e.g., "Top Games", "Recommended for you") and each category has a horizontal list of apps.
  • Expandable lists: Each item in a RecyclerView might expand to reveal another list.

Here's how you can create a nested RecyclerView:

1. Setup the Outer RecyclerView:

The outer RecyclerView will have its items, and each item will contain an inner RecyclerView.

outer_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvCategoryName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Category Name" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/innerRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:overScrollMode="never"
        android:nestedScrollingEnabled="false" />
</LinearLayout>

The android:nestedScrollingEnabled="false" is important as it ensures smooth scrolling when nested.

2. Setup the Inner RecyclerView:

Each item in the inner RecyclerView will have its layout:

inner_item.xml:

<!-- This is a simplistic representation, design as per your needs -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tvItem"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Item" />

3. Setup Adapters:

  • OuterAdapter:
class OuterAdapter(private val dataList: List<OuterModel>) : RecyclerView.Adapter<OuterAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.outer_item, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = dataList[position]
        holder.tvCategoryName.text = item.categoryName
        holder.innerRecyclerView.layoutManager = LinearLayoutManager(holder.innerRecyclerView.context, LinearLayoutManager.HORIZONTAL, false)
        holder.innerRecyclerView.adapter = InnerAdapter(item.innerItems)
    }

    override fun getItemCount() = dataList.size

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvCategoryName: TextView = itemView.findViewById(R.id.tvCategoryName)
        val innerRecyclerView: RecyclerView = itemView.findViewById(R.id.innerRecyclerView)
    }
}
  • InnerAdapter:
class InnerAdapter(private val itemList: List<InnerModel>) : RecyclerView.Adapter<InnerAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.inner_item, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = itemList[position]
        holder.tvItem.text = item.itemName
    }

    override fun getItemCount() = itemList.size

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val tvItem: TextView = itemView.findViewById(R.id.tvItem)
    }
}

4. Model Classes:

data class OuterModel(val categoryName: String, val innerItems: List<InnerModel>)
data class InnerModel(val itemName: String)

5. Instantiate and Setup in your Activity/Fragment:

val outerRecyclerView = findViewById<RecyclerView>(R.id.outerRecyclerView)
outerRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
outerRecyclerView.adapter = OuterAdapter(yourDataList)

6. Optimization:

Ensure to properly handle view recycling. For more complex nesting and improved performance, consider using ConcatAdapter or other tools that might be available in newer versions of the RecyclerView library.

With this setup, you will have a nested RecyclerView. Always be cautious with nested scrolling views as they can cause performance issues if not managed properly. Make sure you test the performance on different devices.

  1. Code example for nested RecyclerView in Android:

    • Here's a simplified example using Kotlin for a parent RecyclerView with a nested RecyclerView:
    class ParentAdapter(private val parentData: List<ParentItem>) :
        RecyclerView.Adapter<ParentAdapter.ParentViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParentViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_parent, parent, false)
            return ParentViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
            val parentItem = parentData[position]
            holder.bind(parentItem)
        }
    
        override fun getItemCount(): Int = parentData.size
    
        inner class ParentViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            private val childRecyclerView: RecyclerView = itemView.findViewById(R.id.childRecyclerView)
    
            fun bind(parentItem: ParentItem) {
                val childAdapter = ChildAdapter(parentItem.childData)
                childRecyclerView.adapter = childAdapter
                // Set up LinearLayoutManager or other layout manager for the child RecyclerView
                childRecyclerView.layoutManager = LinearLayoutManager(itemView.context, RecyclerView.HORIZONTAL, false)
            }
        }
    }
    
    • The associated XML layout (item_parent.xml) might include a RecyclerView for the child items:
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <!-- Other parent item views -->
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/childRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/otherViews"
            android:padding="8dp"/>
    </RelativeLayout>
    

    Adjust the code and layout based on your specific requirements and data structures.