Unlock Multi-Layer: nested RecyclerView horizontal and vertical

A nested RecyclerView is like in an app. It’s a big list that holds other smaller lists, each scrolling independently within the main one.

Think of scrolling through a news app with categories like “Top Stories” and “Entertainment.” Each category is a smaller list within the main RecyclerView, showcasing its own set of articles. You can swipe left or right to switch between categories, then scroll up and down within each category to see individual articles.

A nested RecyclerView is like a container that can hold lists inside other lists. Picture a main list of things going up and down. Now, each of those things in the list can have another list going from left to right. It’s like a list of lists!

People who make apps like using this because it’s great for showing different kinds of stuff. For example, you could have a list of pictures going up and down, and each picture could have a row of smaller pictures going from left to right. It’s handy when you want to mix things up, like having grids inside lists or slideshows inside other slideshows.

How to Create Nested RecyclerViews?

Step 1: Create a New Project in Android Studio

Open Android Studio and click on “Start a new Android Studio project.”

Step 2: Implement MainActivity

Open the MainActivity.java file.

MainActivity with two RecyclerViews—one configured horizontally and the other vertically. It uses custom adapters (HorizontalAdapter and VerticalAdapter) to populate the RecyclerViews with sample data obtained from the getHorizontalData and getVerticalData methods. The layout is defined in activity_main.xml, and each item’s layout is defined in item_horizontal.xml and item_vertical.xml.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private RecyclerView horizontalRecyclerView;
    private RecyclerView verticalRecyclerView;
private Toolbar toolbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar=findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        horizontalRecyclerView = findViewById(R.id.horizontalRecyclerView);
        verticalRecyclerView = findViewById(R.id.verticalRecyclerView);
        // Initialize and set up the horizontal RecyclerView (e.g., using a custom adapter)
        HorizontalAdapter horizontalAdapter = new HorizontalAdapter(getHorizontalData()); // Implement this method
        horizontalRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
        horizontalRecyclerView.setAdapter(horizontalAdapter);
        // Initialize and set up the vertical RecyclerView (e.g., using another custom adapter)
        VerticalAdapter verticalAdapter = new VerticalAdapter(getVerticalData()); // Implement this method
        verticalRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        verticalRecyclerView.setAdapter(verticalAdapter);
    }
    private ArrayList<String> getHorizontalData() {
        ArrayList<String> horizontalData = new ArrayList<>();
        // Add some sample data
        horizontalData.add("Item 1");
        horizontalData.add("Item 2");
        horizontalData.add("Item 3");
        horizontalData.add("Item 4");
        horizontalData.add("Item 5");
        horizontalData.add("Item 6");
        horizontalData.add("Item 7");
        horizontalData.add("Item 8");
        horizontalData.add("Item 9");
        horizontalData.add("Item 10");
        return horizontalData;
    }
    private ArrayList<String> getVerticalData() {
        ArrayList<String> verticalData = new ArrayList<>();
        verticalData.add("Item 1");
        verticalData.add("Item 2");
        verticalData.add("Item 3");
        verticalData.add("Item 4");
        verticalData.add("Item 5");
        verticalData.add("Item 6");
        verticalData.add("Item 7");
        verticalData.add("Item 8");
        verticalData.add("Item 9");
        verticalData.add("Item 10");
        // Add more items as needed
        return verticalData;
    }
}

Explanation

Class Declaration and Member Variables

public class MainActivity extends AppCompatActivity {
    private RecyclerView horizontalRecyclerView;
    private RecyclerView verticalRecyclerView;
    private Toolbar toolbar;

It defines three member variables: horizontalRecyclerView, verticalRecyclerView, and toolbar.

onCreate Method

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        horizontalRecyclerView = findViewById(R.id.horizontalRecyclerView);
        verticalRecyclerView = findViewById(R.id.verticalRecyclerView);

findViewById is used to initialize the toolbar, horizontalRecyclerView, and verticalRecyclerView based on their respective IDs in the layout.

Set Up Horizontal RecyclerView

        HorizontalAdapter horizontalAdapter = new HorizontalAdapter(getHorizontalData());
        horizontalRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
        horizontalRecyclerView.setAdapter(horizontalAdapter);

It initializes a new instance of HorizontalAdapter and passes data obtained from the getHorizontalData method. Configures the horizontalRecyclerView to use a horizontal LinearLayoutManager. Sets the adapter for the horizontalRecyclerView to the horizontalAdapter.

Set Up Vertical RecyclerView

        VerticalAdapter verticalAdapter = new VerticalAdapter(getVerticalData());
        verticalRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        verticalRecyclerView.setAdapter(verticalAdapter);
    }

Initializes a new instance of VerticalAdapter and passes data obtained from the getVerticalData method. Configures the verticalRecyclerView to use a vertical LinearLayoutManager. Sets the adapter for the verticalRecyclerView to the verticalAdapter.

getHorizontalData Method

    private ArrayList<String> getHorizontalData() {
        ArrayList<String> horizontalData = new ArrayList<>();
        // Add some sample data
        horizontalData.add("Item 1");
        horizontalData.add("Item 2");
        // ... (similarly, adds items up to "Item 10")
        return horizontalData;
    }

This method creates and returns an ArrayList containing sample data for the horizontal RecyclerView.

getVerticalData Method

    private ArrayList<String> getVerticalData() {
        ArrayList<String> verticalData = new ArrayList<>();
        // Add some sample data
        verticalData.add("Item 1");
        verticalData.add("Item 2");
        // ... (similarly, adds items up to "Item 10")
        // Add more items as needed
        return verticalData;
    }
}

This method creates and returns an ArrayList containing sample data for the vertical RecyclerView.

Step 3: Design the Layout

Open the res/layout/activity_main.xml file.

Design the layout to include two RecyclerViews and a Toolbar.

activity_main.xml

<!-- res/layout/activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="?attr/actionBarTheme"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/horizontalRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/toolbar"
        android:layout_marginTop="16dp"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/verticalRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/horizontalRecyclerView"
        android:layout_marginTop="16dp"/>
</RelativeLayout>

Step 4: Create a custom_action_bar

custom_action_bar.xml

<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize">
<!--custom text and logo add here-->
</androidx.appcompat.widget.Toolbar>

Step 5: Create HorizontalAdapter Class

Implement the HorizontalAdapter and VerticalAdapter classes to populate data into the RecyclerViews.

The HorizontalAdapter is responsible for managing the data and creating the ViewHolders for a horizontal RecyclerView. It inflates item layouts, binds data to the ViewHolders, and specifies the number of items in the data set. The HorizontalViewHolder is a nested class representing the individual items in the horizontal RecyclerView, and it holds references to the UI elements within each item.

HorizontalAdapter.java

public class HorizontalAdapter extends RecyclerView.Adapter<HorizontalAdapter.HorizontalViewHolder> {
    private ArrayList<String> horizontalList;
    public HorizontalAdapter(ArrayList<String> horizontalList) {
        this.horizontalList = horizontalList;
    }
    @Override
    public HorizontalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_item, parent, false);
        return new HorizontalViewHolder(view);
    }
    @Override
    public void onBindViewHolder(HorizontalViewHolder holder, final int position) {
        holder.txtView.setText(horizontalList.get(position));
    }
    @Override
    public int getItemCount() {
        return horizontalList.size();
    }
    public class HorizontalViewHolder extends RecyclerView.ViewHolder {
        TextView txtView;
        public HorizontalViewHolder(View view) {
            super(view);
            txtView = view.findViewById(R.id.horizontalItemTextView);
        }
    }
}

Explanation

Class Declaration and Constructor

public class HorizontalAdapter extends RecyclerView.Adapter<HorizontalAdapter.HorizontalViewHolder> {
    private ArrayList<String> horizontalList;

    public HorizontalAdapter(ArrayList<String> horizontalList) {
        this.horizontalList = horizontalList;
    }

Declares a class named HorizontalAdapter that extends RecyclerView.Adapter.
Specifies the type of view holder (HorizontalViewHolder) used in the adapter.
Defines a private member variable horizontalList to store the data for the horizontal RecyclerView.
Provides a constructor that takes an ArrayList as a parameter to initialize the adapter with data.

onCreateViewHolder Method

    @Override
    public HorizontalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_item, parent, false);
        return new HorizontalViewHolder(view);
    }

The onCreateViewHolder method is called when the RecyclerView needs a new ViewHolder.
Inflates the layout for a single item (horizontal_item.xml) using the LayoutInflater.
Creates and returns a new instance of HorizontalViewHolder initialized with the inflated view.

onBindViewHolder Method

    @Override
    public void onBindViewHolder(HorizontalViewHolder holder, final int position) {
        holder.txtView.setText(horizontalList.get(position));
    }

The onBindViewHolder method is called to bind data to a ViewHolder at a specific position.
Sets the text of the txtView (a TextView in the HorizontalViewHolder) to the data at the specified position in the horizontalList.

getItemCount Method

    @Override
    public int getItemCount() {
        return horizontalList.size();
    }

The getItemCount method returns the total number of items in the data set.
In this case, it returns the size of the horizontalList, indicating the number of items to be displayed in the horizontal RecyclerView.

Inner Class HorizontalViewHolder

    public class HorizontalViewHolder extends RecyclerView.ViewHolder {
        TextView txtView;

        public HorizontalViewHolder(View view) {
            super(view);
            txtView = view.findViewById(R.id.horizontalItemTextView);
        }
    }

Declares an inner class named HorizontalViewHolder that extends RecyclerView.ViewHolder.
Defines a TextView member variable (txtView) to represent the view in each item.
Provides a constructor that takes a View (item layout) as a parameter and initializes the txtView with the view identified by its ID (R.id.horizontalItemTextView).

Step 6: Create VerticalAdapter Class

The VerticalAdapter is responsible for managing the data and creating the ViewHolders for a vertical RecyclerView. It inflates item layouts, binds data to the ViewHolders, and specifies the number of items in the data set. The ViewHolder is a nested class representing the individual items in the vertical RecyclerView, and it holds references to the UI elements within each item.

VerticalAdapter.java

public class VerticalAdapter extends RecyclerView.Adapter<VerticalAdapter.ViewHolder> {
    private Context context;
    private ArrayList<String> data; // This should be your data source
    // Constructor to initialize the adapter with data
    public VerticalAdapter(ArrayList<String> data) {
        this.context = context;
        this.data = data;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.vertical_item, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String item = data.get(position);
        holder.textView.setText(item);
    }
    @Override
    public int getItemCount() {
        return data.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        public ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.verticalItemTextView);
        }
    }
}

Explanation

Class Declaration and Constructor

public class VerticalAdapter extends RecyclerView.Adapter<VerticalAdapter.ViewHolder> {
    private Context context;
    private ArrayList<String> data;

    public VerticalAdapter(ArrayList<String> data) {
        this.context = context;
        this.data = data;
    }

Declares a class named VerticalAdapter that extends RecyclerView.Adapter.
Specifies the type of view holder (ViewHolder) used in the adapter.
Defines private member variables: context to store the context, and data to store the data for the vertical RecyclerView.
Provides a constructor that takes an ArrayList as a parameter to initialize the adapter with data.

onCreateViewHolder Method

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.vertical_item, parent, false);
        return new ViewHolder(view);
    }

The onCreateViewHolder method is called when the RecyclerView needs a new ViewHolder.
Inflates the layout for a single item (vertical_item.xml) using the LayoutInflater.
Creates and returns a new instance of ViewHolder initialized with the inflated view.

onBindViewHolder Method

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String item = data.get(position);
        holder.textView.setText(item);
    }

The onBindViewHolder method is called to bind data to a ViewHolder at a specific position.
Gets the data at the specified position in the data list.
Sets the text of the textView (a TextView in the ViewHolder) to the retrieved data.

getItemCount Method

    @Override
    public int getItemCount() {
        return data.size();
    }

The getItemCount method returns the total number of items in the data set.
In this case, it returns the size of the data list, indicating the number of items to be displayed in the vertical RecyclerView.

Inner Class ViewHolder

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.verticalItemTextView);
        }
    }

Declares an inner class named ViewHolder that extends RecyclerView.ViewHolder.
Defines a TextView member variable (textView) to represent the view in each item.
Provides a constructor that takes a View (item layout) as a parameter and initializes the textView with the view identified by its ID (R.id.verticalItemTextView).

Step 7: Design the horizontal_item Layout

Create XML layout files for horizontal item views.

horizontal_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- horizontal_item.xml -->
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="8dp">
    <ImageView
        android:id="@+id/horizontalItemImageView"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_launcher_background"
        android:layout_centerHorizontal="true"/>
    <TextView
        android:id="@+id/horizontalItemTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/horizontalItemImageView"
        android:layout_centerHorizontal="true"
        android:text="Item Name"
        android:layout_marginTop="4dp"/>
</RelativeLayout>

Step 7: Design the vertical_item Layout

Create XML layout files for vertical item views.

vertical_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- res/layout/vertical_item.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
    <TextView
        android:id="@+id/verticalItemTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="bold"
        android:text="Item Title" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:text="Item Description" />
</LinearLayout>

Step 8: Run Your App

Build and run your Android app on an emulator or a physical device.

nested recyclerview horizontal and vertical

Leave a Reply