How to create a nested RecyclerView in Android

A nested RecyclerView is an implementation of a RecyclerView within a RecyclerView. An example of such a layout can be seen in a variety of apps such as the Play store where the outer (parent) RecyclerView is of Vertical orientation whereas the inner (child) RecyclerViews are of horizontal orientations. A similar layout is developed here.

Approach:
Step 1:Add the required dependencies
Add the following dependencies to build.gradle (:app) file.The first dependency corresponding to RecyclerView is mandatory and the second one is for CardView, thus it is optional depending upon the UI requirements. Since here CardView is used in the child RecyclerView layout, so the CardView dependency is added.
Note: After adding the dependencies, click on Sync now.

implementation ‘androidx.recyclerview:recyclerview:1.0.0’
implementation ‘androidx.cardview:cardview:1.0.0’

Note: For the correct versions of dependencies check here.
Step 2: Implement the parent RecyclerView
The parent RecyclerView is implemented in the activity_main file. Here, activity_main file only holds the parent RecyclerView, but it can be customized as per the requirements.

activity_main



filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <!-- This is the parent RecyclerView-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/parent_recyclerview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.271" />
  
</androidx.constraintlayout.widget.ConstraintLayout>

chevron_right


Step 3: Create item layout for the parent RecyclerView
Identify requirements for the parent layout and add Views corresponding to them in an XML layout file. Here, layout files are named as parent_item. In addition to the child RecyclerView, a TextView for the title is included.

parent_item

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
  
    <!--Title-->
  
    <TextView
        android:id="@+id/parent_item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="12sp"
        android:textSize="18sp"
        />
  
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="12dp"
            android:orientation="horizontal">
  
            <!--Child RecyclerView-->
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/child_recyclerview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        </LinearLayout>
  
  
</LinearLayout>

chevron_right


Step 4: Create item layout for the child RecyclerView
The layout of the items of the child RecyclerView is created in an XML layout file named child_item. Child RecyclerView includes an ImageView and a TextView, both wrapped inside a CardView.
The following image is used as the resource of the ImageView, thus it is added in the drawable resouce folder.

icon

child_item

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
  
    <!--CardView that holds the elements
        of the child RecyclerView -->
    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
  
            <!--Image in the CardView-->
            <!--Here we have already given
                the source for the ImageView
                and we will not assign it
                in the Java code-->
            <!--So all the ImageViews will
                hold the same image-->
            <ImageView
                android:id="@+id/img_child_item"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_marginStart="5dp"
                android:background="@color/colorPrimaryDark"
                android:src="@drawable/icon"/>
  
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="60dp"
                android:layout_toEndOf="@id/img_child_item"
                android:padding="12dp"
                android:layout_below="@+id/img_child_item"
                android:layout_alignParentStart="true"
                android:orientation="vertical">
  
                <!--Text in the CardView-->
                <TextView
                    android:id="@+id/child_item_title"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textStyle="bold"
                    />
            </LinearLayout>
        </RelativeLayout>
    </androidx.cardview.widget.CardView>
  
</FrameLayout>

chevron_right


Step 5: Create Item classes for each of the RecyclerViews.
A Java class is required for each RecyclerView wherein the constructor initializes the parameters of the item and the getter and setter methods are declared. Thus, create the following Java classes:

  • ChildItem: This class will implement the constructor, getter, and setter methods for the Views of the child_item layout that we wish to set dynamically.
  • ParentItem: This class will implement the constructor, getter, and setter methods for the Views of the parent_item layout that we wish set dynamically.

ChildItem

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.nestedrecyclerview;
  
public class ChildItem {
  
    // Declaration of the variable
    private String ChildItemTitle;
  
    // Constructor of the class
    // to initialize the variable*
    public ChildItem(String childItemTitle)
    {
        this.ChildItemTitle = childItemTitle;
    }
  
    // Getter and Setter method
    // for the parameter
    public String getChildItemTitle()
    {
        return ChildItemTitle;
    }
  
    public void setChildItemTitle(
        String childItemTitle)
    {
        ChildItemTitle = childItemTitle;
    }
}

chevron_right


ParentItem

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.nestedrecyclerview;
  
import java.util.List;
  
public class ParentItem {
  
    // Declaration of the variables
    private String ParentItemTitle;
    private List<ChildItem> ChildItemList;
  
    // Constructor of the class
    // to initialize the variables
    public ParentItem(
        String ParentItemTitle,
        List<ChildItem> ChildItemList)
    {
  
        this.ParentItemTitle = ParentItemTitle;
        this.ChildItemList = ChildItemList;
    }
  
    // Getter and Setter methods
    // for each parameter
    public String getParentItemTitle()
    {
        return ParentItemTitle;
    }
  
    public void setParentItemTitle(
        String parentItemTitle)
    {
        ParentItemTitle = parentItemTitle;
    }
  
    public List<ChildItem> getChildItemList()
    {
        return ChildItemList;
    }
  
    public void setChildItemList(
        List<ChildItem> childItemList)
    {
        ChildItemList = childItemList;
    }
}

chevron_right


Step 6: Create an Adapter class for each of the RecyclerViews.
An adapter class is required to pass the data that is to be displayed in the views of RecyclerView.
An adapter class is needed for the ChildItem as well as ParentItem classes.

  • ChildAdapter: This is the adapter class for holding the information that is to be displayed in the views of the ChildItem class.
  • ParentAdapter: This is the adapter class for holding the information that is to be displayed in the views of the ParentItem class.

In the ParentItemAdapter class, an instance of the class is created

RecyclerView.RecycledViewPool

This class is used to pass Views between the parent RecyclerView and the child RecyclerView.

ChildItemAdapter

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.nestedrecyclerview;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import java.util.List;
  
public class ChildItemAdapter
    extends RecyclerView
                .Adapter<ChildItemAdapter.ChildViewHolder> {
  
    private List<ChildItem> ChildItemList;
  
    // Constuctor
    ChildItemAdapter(List<ChildItem> childItemList)
    {
        this.ChildItemList = childItemList;
    }
  
    @NonNull
    @Override
    public ChildViewHolder onCreateViewHolder(
        @NonNull ViewGroup viewGroup,
        int i)
    {
  
        // Here we inflate the corresponding
        // layout of the child item
        View view = LayoutInflater
                        .from(viewGroup.getContext())
                        .inflate(
                            R.layout.child_item,
                            viewGroup, false);
  
        return new ChildViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(
        @NonNull ChildViewHolder childViewHolder,
        int position)
    {
  
        // Create an instance of the ChildItem
        // class for the given position
        ChildItem childItem
            = ChildItemList.get(position);
  
        // For the created instance, set title.
        // No need to set the image for
        // the ImageViews because we have
        // provided the source for the images
        // in the layout file itself
        childViewHolder
            .ChildItemTitle
            .setText(childItem.getChildItemTitle());
    }
  
    @Override
    public int getItemCount()
    {
  
        // This method returns the number
        // of items we have added
        // in the ChildItemList
        // i.e. the number of instances
        // of the ChildItemList
        // that have been created
        return ChildItemList.size();
    }
  
    // This class is to initialize
    // the Views present
    // in the child RecyclerView
    class ChildViewHolder
        extends RecyclerView.ViewHolder {
  
        TextView ChildItemTitle;
  
        ChildViewHolder(View itemView)
        {
            super(itemView);
            ChildItemTitle
                = itemView.findViewById(
                    R.id.child_item_title);
        }
    }
}

chevron_right


ParentItemAdapter

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.nestedrecyclerview;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
  
import java.util.List;
  
public class ParentItemAdapter
    extends RecyclerView
                .Adapter<ParentItemAdapter.ParentViewHolder> {
  
    // An object of RecyclerView.RecycledViewPool
    // is created to share the Views
    // between the child and
    // the parent RecyclerViews
    private RecyclerView.RecycledViewPool
        viewPool
        = new RecyclerView
              .RecycledViewPool();
    private List<ParentItem> itemList;
  
    ParentItemAdapter(List<ParentItem> itemList)
    {
        this.itemList = itemList;
    }
  
    @NonNull
    @Override
    public ParentViewHolder onCreateViewHolder(
        @NonNull ViewGroup viewGroup,
        int i)
    {
  
        // Here we inflate the corresponding
        // layout of the parent item
        View view = LayoutInflater
                        .from(viewGroup.getContext())
                        .inflate(
                            R.layout.parent_item,
                            viewGroup, false);
  
        return new ParentViewHolder(view);
    }
  
    @Override
    public void onBindViewHolder(
        @NonNull ParentViewHolder parentViewHolder,
        int position)
    {
  
        // Create an instance of the ParentItem
        // class for the given position
        ParentItem parentItem
            = itemList.get(position);
  
        // For the created instance,
        // get the title and set it
        // as the text for the TextView
        parentViewHolder
            .ParentItemTitle
            .setText(parentItem.getParentItemTitle());
  
        // Create a layout manager
        // to assign a layout
        // to the RecyclerView.
  
        // Here we have assigned the layout
        // as LinearLayout with vertical orientation
        LinearLayoutManager layoutManager
            = new LinearLayoutManager(
                parentViewHolder
                    .ChildRecyclerView
                    .getContext(),
                LinearLayoutManager.HORIZONTAL,
                false);
  
        // Since this is a nested layout, so
        // to define how many child items
        // should be prefetched when the
        // child RecyclerView is nested
        // inside the parent RecyclerView,
        // we use the following method
        layoutManager
            .setInitialPrefetchItemCount(
                parentItem
                    .getChildItemList()
                    .size());
  
        // Create an instance of the child
        // item view adapter and set its
        // adapter, layout manager and RecyclerViewPool
        ChildItemAdapter childItemAdapter
            = new ChildItemAdapter(
                parentItem
                    .getChildItemList());
        parentViewHolder
            .ChildRecyclerView
            .setLayoutManager(layoutManager);
        parentViewHolder
            .ChildRecyclerView
            .setAdapter(childItemAdapter);
        parentViewHolder
            .ChildRecyclerView
            .setRecycledViewPool(viewPool);
    }
  
    // This method returns the number
    // of items we have added in the
    // ParentItemList i.e. the number
    // of instances we have created
    // of the ParentItemList
    @Override
    public int getItemCount()
    {
  
        return itemList.size();
    }
  
    // This class is to initialize
    // the Views present in
    // the parent RecyclerView
    class ParentViewHolder
        extends RecyclerView.ViewHolder {
  
        private TextView ParentItemTitle;
        private RecyclerView ChildRecyclerView;
  
        ParentViewHolder(final View itemView)
        {
            super(itemView);
  
            ParentItemTitle
                = itemView
                      .findViewById(
                          R.id.parent_item_title);
            ChildRecyclerView
                = itemView
                      .findViewById(
                          R.id.child_recyclerview);
        }
    }
}

chevron_right


Step 7: Set the layout of parent RecyclerView and pass the arguments to both the RecyclerViews. The arguments to be passed to the RecyclerViews are given in the Java class that inflates the activity of the parent RecyclerView (here activity_main). So here the arguments will be passed in the MainActivity file.
Also, set the layout for the parent RecyclerView here itself.

MainActivity

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.nestedrecyclerview;
  
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.ArrayList;
import java.util.List;
  
public class MainActivity
    extends AppCompatActivity {
  
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        RecyclerView
            ParentRecyclerViewItem
            = findViewById(
                R.id.parent_recyclerview);
  
        // Initialise the Linear layout manager
        LinearLayoutManager
            layoutManager
            = new LinearLayoutManager(
                MainActivity.this);
  
        // Pass the arguments
        // to the parentItemAdapter.
        // These arguments are passed
        // using a method ParentItemList()
        ParentItemAdapter
            parentItemAdapter
            = new ParentItemAdapter(
                ParentItemList());
  
        // Set the layout manager
        // and adapter for items
        // of the parent recyclerview
        ParentRecyclerViewItem
            .setAdapter(parentItemAdapter);
        ParentRecyclerViewItem
            .setLayoutManager(layoutManager);
    }
  
    private List<ParentItem> ParentItemList()
    {
        List<ParentItem> itemList
            = new ArrayList<>();
  
        ParentItem item
            = new ParentItem(
                "Title 1",
                ChildItemList());
        itemList.add(item);
        ParentItem item1
            = new ParentItem(
                "Title 2",
                ChildItemList());
        itemList.add(item1);
        ParentItem item2
            = new ParentItem(
                "Title 3",
                ChildItemList());
        itemList.add(item2);
        ParentItem item3
            = new ParentItem(
                "Title 4",
                ChildItemList());
        itemList.add(item3);
  
        return itemList;
    }
  
    // Method to pass the arguments
    // for the elements
    // of child RecyclerView
    private List<ChildItem> ChildItemList()
    {
        List<ChildItem> ChildItemList
            = new ArrayList<>();
  
        ChildItemList.add(new ChildItem("Card 1"));
        ChildItemList.add(new ChildItem("Card 2"));
        ChildItemList.add(new ChildItem("Card 3"));
        ChildItemList.add(new ChildItem("Card 4"));
  
        return ChildItemList;
    }
}

chevron_right


Output:

Attention reader! Don’t stop learning now. Get hold of all the important Java and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.