1. Code
  2. Coding Fundamentals
  3. Tools

Getting Started With RecyclerView and CardView on Android

Scroll to top

Have you ever wanted to create an app where you had to display data to users in a list? This could be anything like a to-do list, shopping list, friend list, contact list, etc. One important characteristic of these types of lists is that their data usually has to be displayed in similarly styled containers. For example, if you are creating a contact list, you will probably show the name and number of each contact in the list.

There are two very useful views that you can use in Android. These are named the CardView and the RecyclerView. The CardView is useful for showcasing data related to individual items in a list. The RecyclerView is useful for showcasing a list of those items.

In this tutorial, you will learn how to use both these views together to create a list of people in the neighborhood.

Initial Setup

Open Android Studio and click on the New Project button. Select Empty Activity and then click the Next button.

New Project WindowNew Project WindowNew Project Window

On the next screen, set the name of the app to whatever you want. I have set it to RecyclerCard. Keep the language set to Kotlin as we will be writing Kotlin code, which is now the recommended language to use for Android development. Set the Minimum SDK to any value greater than or equal to 23. Click Finish once you are done.

Project Name and Language SettingsProject Name and Language SettingsProject Name and Language Settings

You can also set it to a lower value, but you will then have to add the following dependencies to your build.gradle file.

1
implementation 'androidx.cardview:cardview:1.0.0'
2
implementation 'androidx.recyclerview:recyclerview:1.3.0'

Creating a CardView

A CardView is ideal when you want to display your data or item in containers with a similar style. It is basically a FrameLayout with a rounded corner background and shadow. Native support for CardView was added in Lollipop, where it uses the elevation property for shadows. Older platforms rely on a custom emulated shadow to achieve the same effect.

You can create an empty CardView by using the following XML:

1
<androidx.cardview.widget.CardView xmlns:android="https://schemas.android.com/apk/res/android"
2
    xmlns:app="http://schemas.android.com/apk/res-auto"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:id="@+id/card_view"
5
    android:layout_width="match_parent"
6
    android:layout_height="160dp" >
7
    
8
</androidx.cardview.widget.CardView>

Any empty CardView isn't going to be very useful. We will be using it to display information about the people in our neighborhood. So let's add some widgets inside our CardView to display a picture, name, age, and profession.

Our CardView is going to be one part of the larger app. So we will place the XML code for the CardView UI inside a file called item.xml. You can create this file by navigating to the layout folder and then right-clicking on it to add a new Layout Resource File.

The full XML will look something like this:

1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:id="@+id/card_view"
6
    android:layout_width="match_parent"
7
    android:layout_height="160dp"
8
    android:layout_marginStart="20dp"
9
    android:layout_marginTop="16dp"
10
    android:layout_marginEnd="20dp"
11
    app:cardCornerRadius="10dp">
12
13
    <RelativeLayout
14
        android:layout_width="match_parent"
15
        android:layout_height="wrap_content"
16
        android:padding="16dp">
17
18
        <ImageView
19
            android:id="@+id/avatar"
20
            android:layout_width="120dp"
21
            android:layout_height="120dp"
22
            tools:srcCompat="@tools:sample/avatars" />
23
24
        <LinearLayout
25
            android:layout_width="match_parent"
26
            android:layout_height="wrap_content"
27
            android:layout_marginStart="20dp"
28
            android:layout_marginTop="20dp"
29
            android:layout_toEndOf="@+id/avatar"
30
            android:orientation="vertical">
31
32
            <TextView
33
                android:id="@+id/person_name"
34
                android:layout_width="wrap_content"
35
                android:layout_height="wrap_content"
36
                android:fontFamily="sans-serif-black"
37
                android:textColor="@color/black"
38
                android:textSize="24sp"
39
                tools:text="Michael" />
40
41
            <TextView
42
                android:id="@+id/person_age"
43
                android:layout_width="wrap_content"
44
                android:layout_height="wrap_content"
45
                android:textColor="@color/teal_700"
46
                tools:text="30 Years" />
47
48
            <TextView
49
                android:id="@+id/person_job"
50
                android:layout_width="wrap_content"
51
                android:layout_height="wrap_content"
52
                android:textColor="@color/purple_700"
53
                android:textSize="20sp"
54
                tools:text="Accountant" />
55
56
        </LinearLayout>
57
    </RelativeLayout>
58
59
</androidx.cardview.widget.CardView>

Our CardView contains a RelativeLayout widget that contains an ImageView widget and a LinearLayout widget. The LinearLayout widget contains three more TextView widgets that hold the person's name, age, and profession.

The following image shows the empty and the populated CardView widget:

Empty and Populated CardViewEmpty and Populated CardViewEmpty and Populated CardView

Creating a RecyclerView

Using a RecyclerView is a bit more complicated than creating a CardView. This is because simply writing the required XML isn't enough; you have to also write some Kotlin or Java code to populate it with data.

Consider the following XML, which goes in our activity_main.xml file. It contains a RecyclerView below a TextView.

1
<?xml version="1.0" encoding="utf-8"?>
2
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    tools:context=".MainActivity">
8
9
    <TextView
10
        android:id="@+id/heading"
11
        android:layout_width="match_parent"
12
        android:layout_height="wrap_content"
13
        android:text="MY NEIGHBORS"
14
        android:textAlignment="center"
15
        android:layout_marginTop="20dp"
16
        android:textSize="30sp"
17
        android:textColor="@color/black"
18
        android:fontFamily="sans-serif-black"
19
        app:layout_constraintTop_toTopOf="parent" />
20
21
    <androidx.recyclerview.widget.RecyclerView
22
        android:id="@+id/recycler_view"
23
        android:layout_width="match_parent"
24
        android:layout_height="match_parent"
25
        android:layout_marginTop="80dp"
26
        app:layout_constraintTop_toBottomOf="@id/heading" />
27
28
</androidx.constraintlayout.widget.ConstraintLayout>

The preview of this layout file will show you the heading My Neighbors and then a list of items titled item 0, item 1, item 2, and so on. However, installing the app on a device will only show the heading and nothing else. This is because we haven't written any Kotlin code to populate the RecyclerView.

The RecyclerView library dynamically creates elements based on the data that you supply and the layout information you have provided to present the items. This widget provides significant gains in performance when displaying a large amount of data because it recycles elements that have scrolled off the screen.

Now, we will write some code that populates our RecyclerView widget.

Creating Helper Classes

Your MainActivity.kt file will already have some code in it. Position your cursor below and outside the MainActivity class, and add the following line:

1
data class Person(val name: String, val age: Int, val job: String, val photoId: Int)

It will create a new data class to hold data about different people in Person objects. We are using it to store four pieces of information: the person's name as a string, their age as an integer, their job as a string, and a photo ID as an integer.

Now, add the following line inside the MainActivity class, just above the onCreate() method.

1
private val persons: MutableList<Person> = mutableListOf()

This line declares a private and mutable list of Person objects. Currently, the list is empty, but we will populate it soon. Add the following method inside the MainActivity class:

1
private fun initializeData() {
2
    persons.add(Person("Emma Wilson", 23, "Architect", R.drawable.emma))
3
    persons.add(Person("Jack Johnson", 25, "Comedian", R.drawable.jack))
4
    persons.add(Person("Larry James", 35, "Cook", R.drawable.larry))
5
}

We will call this method from within our onCreate() method to populate our persons list. Here, we are providing the name, age, profession, and avatar of different people. The avatar argument contains a reference to different drawable resources, which are simple png files.

Now, we will define another class called RVAdapter, which is a custom adapter class that extends RecyclerView.Adapter. This class will take our list of Person objects as its constructor argument. The adapter is responsible for providing views for each item in our list. Here is the complete code for the RVAdapter class:

1
class RVAdapter(private val persons: List<Person>) :
2
    RecyclerView.Adapter<RVAdapter.PersonViewHolder>() {
3
4
    class PersonViewHolder(itemView: View) :
5
        RecyclerView.ViewHolder(itemView) {
6
        var personName: TextView = itemView.findViewById(R.id.person_name)
7
        var personAge: TextView = itemView.findViewById(R.id.person_age)
8
        var personJob: TextView = itemView.findViewById(R.id.person_job)
9
        var personPhoto: ImageView = itemView.findViewById(R.id.avatar)
10
    }
11
12
    override fun getItemCount(): Int {
13
        return persons.size
14
    }
15
16
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): PersonViewHolder {
17
        val v: View =
18
            LayoutInflater.from(viewGroup.context).inflate(R.layout.item, viewGroup, false)
19
        return PersonViewHolder(v)
20
    }
21
22
    override fun onBindViewHolder(personViewHolder: PersonViewHolder, idx: Int) {
23
        personViewHolder.personName.text = persons[idx].name
24
        personViewHolder.personAge.text = "${persons[idx].age} Years Old"
25
        personViewHolder.personJob.text = persons[idx].job
26
        personViewHolder.personPhoto.setImageResource(persons[idx].photoId)
27
    }
28
}

There are a few things to note here. First, we are overriding three different methods called getItemCount(), onCreateViewHolder(), and onBindViewHolder(). It also contains an inner class called PersonViewHolder, which holds a reference to the views within each item of the RecyclerView. In this particular case, it contains the reference to the three different TextView widgets and one ImageView widget.

The getItemCount() method is used internally to determine the number of items. We override this method to provide correct information about the number of items in our list.

The onCreateViewHolder() method creates and returns a new PersonViewHolder object for each item in the list. You can see that we are passing the layout file for our CardView to the inflate() method here. The onBindViewHolder() method provides data binding for the views within the view holder.

Updating the onCreate() Method

Now that we have all the helper code in place, we can update the onCreate() method for our MainActivity. Here is the code for our implementation of the onCreate() method:

1
override fun onCreate(savedInstanceState: Bundle?) {
2
    super.onCreate(savedInstanceState)
3
    setContentView(R.layout.activity_main)
4
5
    val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
6
    recyclerView.setHasFixedSize(true)
7
8
    val linearLayoutManager = LinearLayoutManager(this)
9
    recyclerView.layoutManager = linearLayoutManager
10
11
    initializeData()
12
13
    val adapter = RVAdapter(persons)
14
    recyclerView.adapter = adapter
15
}

We begin by setting the layout for our activity using the setContentView() method, where we pass our main layout file. After that, we find a reference to our RecyclerView and then create a layout manager to be used with this view.

We make a call to the initializeData() method on the next line, and it adds some persons to our empty list. Then, we create a new instance of our RVAdapter class using our list of persons as an argument. The adapter of our RecyclerView is then set to the RVAdapter object we just created.

Run your app now, and you should see something like the image below.

RecyclerView App Final ResultRecyclerView App Final ResultRecyclerView App Final Result

The left screen shows what the app looks like without our adapter. As you can see, the RecyclerView doesn't render anything unless we provide data. The image files are from an Avatar icon set on Reshot. These are just png files that you need to place in the drawable folder.

Final Thoughts

In this tutorial, you learned the basics of creating a CardView and RecyclerView in Android. Both these views are generally used together to display a list of items that contain similar data. RecyclerView provides a huge performance boost for large lists because it recycles items in your list that have scrolled off the screen. You should prefer using RecyclerView whenever displaying data in lists.

Our app is just fine if we want to display data to users. However, we cannot interact with the data in its current state. In our next tutorial, we will show you how to select multiple items from any RecyclerView list.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.