How to Create RecyclerView with Multiple ViewType in Android?

RecyclerView forms a very crucial part of the UI in Android App development. It is especially important to optimize memory consumption during the display of a long list of items. A RecylerView inflates a customized list of items. This list can have either all similar layouts or multiple distinct layouts. Here, such a RecyclerView with multiple ViewTypes is developed. Following is an example of Android RecyclerView with multiple views.
multiple-viewtype

Approach

Step 1: Add the required dependencies
Create a new project in Android Studio and add the following dependencies in build.gradle(:app) under the Gradle Scripts section:

implementation “androidx.recyclerview:recyclerview:1.1.0”
implementation “androidx.cardview:cardview:1.0.0”

For more up-to-date versions of the dependencies, click here. While the first dependency is mandatory, the second one is optional depending upon the UI requirements. Click on Sync Now and proceed.

Step 2: Implement RecyclerView in activity_main.xml



Create a layout that holds the main RecyclerView. Here, it has been created in the activity_main.xml file. The given layout contains merely a Welcome TextView and a RecyclerView, however, it can be customized as per the requirements. Code for activity_main.xml is given below.

activity_main.xml

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">
  
    <!--Welcome text-->
    <TextView
        android:id="@+id/heading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Welcome to GFG!"
        android:textColor="#006600"
        android:textSize="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.058"></TextView>
  
    <!-- Main RecyclerView-->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_marginStart="15dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/heading"
        app:layout_constraintVertical_bias="0.061"
        android:paddingBottom="100dp"/>
  
</androidx.constraintlayout.widget.ConstraintLayout>

chevron_right


Step 3: Add the required drawable file

Before proceeding further, make sure all the necessary drawable resources are added under the drawable resource directory. In this tutorial, only the following icon has been used:
icon_two

Step 4: Create all the item layouts

Identify all the different layouts the RecyclerView is required to hold and implement them all in separate XML files under the layout resource directory. Here, two distinct layouts have been created. The first one is implemented in layout_one.xml while the second one in layout_two.xml. The first layout consists of just a TextView wrapped inside a CardView. The following is its implementation.

layout_one.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
  
    <!--parent CardView-->
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview_one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:elevation="5dp">
  
        <!--LinearLayout inside the CardView-->
        <!--This layout is accessed to create
            toasts when this item is clicked-->
        <LinearLayout
            android:id="@+id/linearlayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
  
            <!--This layout only holds a TextView
                inside a CardView-->
            <TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#000000"
                android:textSize="20dp"
                android:layout_margin="20dp"/>
  
        </LinearLayout>
    </androidx.cardview.widget.CardView>
  
    <!-- This is extra space given to maintain a 
         gap between two consecutive CardViews-->
    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp"/>
  
</LinearLayout>

chevron_right


The second item holds three elements wrapped inside a CardView.



  • An ImageView
  • A TextView
  • Another TextView with a relatively smaller font size

layout_two.xml

filter_none

edit
close

play_arrow

link
brightness_4
code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:id="@+id/linearlayout"
    >
    <!--parent CardView-->
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview_two"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:elevation="5dp">
  
        <!--LinearLayout inside the CardView-->
        <!--This layout is accessed to create
             toasts when this item is clicked-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
  
            <!--This layout consists of an ImageView 
                and two TextViews-->
            <ImageView
                android:id="@+id/image"
                android:layout_width="80dp"
                android:layout_height="80dp"/>
  
            <!-- The purpose of this LinearLayout  is 
                 to align the two TextViews Vertically-->
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="vertical">
  
                <!--These are the 2 TextViews in this layout-->
                <TextView
                    android:id="@+id/text_one"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="10dp"
                    android:layout_marginStart="20dp"
                    android:textColor="#000000"
                    android:textSize="20dp"/>
  
                <TextView
                    android:id="@+id/text_two"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000000"
                    android:textSize="15dp"
                    android:layout_marginTop="10dp"
                    android:layout_marginStart="20dp"/>
  
            </LinearLayout>
        </LinearLayout>
  
    </androidx.cardview.widget.CardView>
    <!-- This is extra space given to 
         maintain a gap between two CardViews-->
    <Space
        android:layout_width="match_parent"
        android:layout_height="10dp"/>
  
</LinearLayout>

chevron_right


Step 5: Create an Item class

Create a Java class that holds the public constructors corresponding to each layout. Thus, two constructors have been created here in the ItemClass.java file. In addition to constructors, the getter and setter methods too are declared here. This is done in order to safely access the private variables of the ItemClass outside of it. This is how the ItemClass.java looks for the layouts created above:

ItemClass.java

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.android.multilayoutrecyclerview;
  
// ItemClass
  
public class ItemClass {
  
    // Integers assigned to each layout
    // these are declared static so that they can
    // be accessed from the class name itself
    // And final so that they are not modified later
    public static final int LayoutOne = 0;
    public static final int LayoutTwo = 1;
  
    // This variable ViewType specifies
    // which out of the two layouts
    // is expected in the given item
    private int viewType;
  
    // String variable to hold the TextView
    // of the first item.
    private String text;
  
    // public constructor for the first layout
    public ItemClass(int viewType, String text)
    {
        this.text = text;
        this.viewType = viewType;
    }
  
    // getter and setter methods for the text variable
  
    public String getText() { return text; }
  
    public void setText(String text) { this.text = text; }
  
    // Variables for the item of second layout
    private int icon;
    private String text_one, text_two;
  
    // public constructor for the second layout
    public ItemClass(int viewType, int icon, String text_one,
                     String text_two)
    {
        this.icon = icon;
        this.text_one = text_one;
        this.text_two = text_two;
        this.viewType = viewType;
    }
  
    // getter and setter methods for
    // the variables of the second layout
  
    public int geticon() { return icon; }
  
    public void seticon(int icon) { this.icon = icon; }
  
    public String getText_one() { return text_one; }
  
    public void setText_one(String text_one)
    {
        this.text_one = text_one;
    }
  
    public String getText_two() { return text_two; }
  
    public void setText_two(String text_two)
    {
        this.text_two = text_two;
    }
  
    public int getViewType() { return viewType; }
  
    public void setViewType(int viewType)
    {
        this.viewType = viewType;
    }
}

chevron_right


Step 6: Create the Adapter class

Create an adapter class to display the contents of the RecyclerView. In the Adapter class for multiple ViewType RecyclerViews, the following method is overridden in addition to the conventional onCreateViewHolder(), onBindViewHolder() and getItemCount() methods. getItemViewType() method is solely responsible for choosing the layout corresponding to each item. Apart from adding an extra method, the other changes include defining a specific ViewHolder class for each of the item layouts. Follow the code given for a deeper understanding.

AdapterClass.java

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.android.multilayoutrecyclerview;
  
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
  
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
  
import java.util.List;
  
import static com.example.android.multilayoutrecyclerview.ItemClass.LayoutOne;
import static com.example.android.multilayoutrecyclerview.ItemClass.LayoutTwo;
  
public class AdapterClass extends RecyclerView.Adapter {
  
    private List<ItemClass> itemClassList;
  
    // public constructor for this class
    public AdapterClass(List<ItemClass> itemClassList)
    {
        this.itemClassList = itemClassList;
    }
  
    // Override the getItemViewType method.
    // This method uses a switch statement
    // to assign the layout to each item
    // depending on the viewType passed
  
    @Override
    public int getItemViewType(int position)
    {
        switch (itemClassList.get(position).getViewType()) {
        case 0:
            return LayoutOne;
        case 1:
            return LayoutTwo;
        default:
            return -1;
        }
    }
  
    // Create classes for each layout ViewHolder.
  
    class LayoutOneViewHolder
        extends RecyclerView.ViewHolder {
  
        private TextView textview;
        private LinearLayout linearLayout;
  
        public LayoutOneViewHolder(@NonNull View itemView)
        {
            super(itemView);
  
            // Find the Views
            textview = itemView.findViewById(R.id.text);
            linearLayout
                = itemView.findViewById(R.id.linearlayout);
        }
  
        // method to set the views that will
        // be used further in onBindViewHolder method.
        private void setView(String text)
        {
  
            textview.setText(text);
        }
    }
  
    // similarly a class for the second layout is also
    // created.
  
    class LayoutTwoViewHolder
        extends RecyclerView.ViewHolder {
  
        private ImageView icon;
        private TextView text_one, text_two;
        private LinearLayout linearLayout;
  
        public LayoutTwoViewHolder(@NonNull View itemView)
        {
            super(itemView);
            icon = itemView.findViewById(R.id.image);
            text_one = itemView.findViewById(R.id.text_one);
            text_two = itemView.findViewById(R.id.text_two);
            linearLayout
                = itemView.findViewById(R.id.linearlayout);
        }
  
        private void setViews(int image, String textOne,
                              String textTwo)
        {
            icon.setImageResource(image);
            text_one.setText(textOne);
            text_two.setText(textTwo);
        }
    }
  
    // In the onCreateViewHolder, inflate the
    // xml layout as per the viewType.
    // This method returns either of the
    // ViewHolder classes defined above,
    // depending upon the layout passed as a parameter.
  
    @NonNull
    @Override
    public RecyclerView.ViewHolder
    onCreateViewHolder(@NonNull ViewGroup parent,
                       int viewType)
    {
        switch (viewType) {
        case LayoutOne:
            View layoutOne
                = LayoutInflater.from(parent.getContext())
                      .inflate(R.layout.layout_one, parent,
                               false);
            return new LayoutOneViewHolder(layoutOne);
        case LayoutTwo:
            View layoutTwo
                = LayoutInflater.from(parent.getContext())
                      .inflate(R.layout.layout_two, parent,
                               false);
            return new LayoutTwoViewHolder(layoutTwo);
        default:
            return null;
        }
    }
  
    // In onBindViewHolder, set the Views for each element
    // of the layout using the methods defined in the
    // respective ViewHolder classes.
  
    @Override
    public void onBindViewHolder(
        @NonNull RecyclerView.ViewHolder holder,
        int position)
    {
  
        switch (itemClassList.get(position).getViewType()) {
        case LayoutOne:
  
            String text
                = itemClassList.get(position).getText();
            ((LayoutOneViewHolder)holder).setView(text);
  
            // The following code pops a toast message
            // when the item layout is clicked.
            // This message indicates the corresponding
            // layout.
            ((LayoutOneViewHolder)holder)
                .linearLayout.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view)
                        {
  
                            Toast
                                .makeText(
                                    view.getContext(),
                                    "Hello from Layout One!",
                                    Toast.LENGTH_SHORT)
                                .show();
                        }
                    });
  
            break;
  
        case LayoutTwo:
            int image
                = itemClassList.get(position).geticon();
            String text_one
                = itemClassList.get(position).getText_one();
            String text_two
                = itemClassList.get(position).getText_two();
            ((LayoutTwoViewHolder)holder)
                .setViews(image, text_one, text_two);
            ((LayoutTwoViewHolder)holder)
                .linearLayout.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View view)
                        {
  
                            Toast
                                .makeText(
                                    view.getContext(),
                                    "Hello from Layout Two!",
                                    Toast.LENGTH_SHORT)
                                .show();
                        }
                    });
            break;
        default:
            return;
        }
    }
  
    // This method returns the count of items present in the
    // RecyclerView at any given time.
  
    @Override
    public int getItemCount()
    {
        return itemClassList.size();
    }
}

chevron_right


Step 7: Complete the MainActivity.java file

Following are the important tasks to be implemented in the MainActivity.java file.

  • Set the content view as the XML activity wherein the main RecyclerView has been implemented, here activity_main.xml.
  • Set the layout for the RecyclerView.
  • Pass arguments to the RecyclerView.
  • Set the Adapter.

MainActivity.java

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.android.multilayoutrecyclerview;
  
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
  
import android.os.Bundle;
import android.widget.Adapter;
  
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);
  
        // From the MainActivity, find the RecyclerView.
        RecyclerView recyclerView
            = findViewById(R.id.recyclerView);
  
        // Create and set the layout manager
        // For the RecyclerView.
        LinearLayoutManager layoutManager
            = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
  
        List<ItemClass> itemClasses = new ArrayList<>();
  
        // pass the arguments
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        itemClasses.add(new ItemClass(ItemClass.LayoutOne,
                                      "Item Type 1"));
        itemClasses.add(new ItemClass(
            ItemClass.LayoutTwo, R.drawable.icon,
            "Item Type 2", "Text"));
        AdapterClass adapterClass
            = new AdapterClass(itemClasses);
  
        AdapterClass adapter
            = new AdapterClass(itemClasses);
  
        // set the adapter
        recyclerView.setAdapter(adapter);
    }
}

chevron_right


Output: Run on Emulator

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 :


Be the First to upvote.


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