This article presumes that you know at least basics of Android Development, including using Android Studio and creating a simple one-screen app with a list in it. Also, Kotlin. Now that is clear, let's head to using the RecyclerView.

If you want to add a list to your app, the obvious choice is a RecyclerView. Let's use it, and add some cards for the list to make it look cool! (Who does not like cards?)

We start with creating a simple application in Android Studio by clicking New Project... and then using the Basic Activity template for the application. You need to choose Kotlin as Language, and after clicking Finish, add following dependencies in the app/build.gradle file.

implementation 'androidx.core:core-ktx:1.2.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
Add the dependencies in app/build.gradle file

Write the base code

Let's write the necessary code, after which we can experiment with the list.

Activity class

In Activity class, we initialize the RecyclerView with a LayoutManager, and an Adapter for the child items.

package dev.aruke.sampleapp

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        recyclerView.apply {
            layoutManager = LinearLayoutManager(this@MainActivity)
            adapter = Adapter()
        }
    }
}
MainActivity.kt

Activity Layout

The layout contains various elements, but the important one is the RecyclerView.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/ic_favorite_black_24dp" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
activity_main.xml

Item layout

The layout represents the view for each child item. It has a simple CardView.

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

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:layout_margin="16dp" />

</FrameLayout>
item_layout.xml

Adapter

Obviously, we have to write an Adapter. Though this article does not include its explanation, here's the code.

package dev.aruke.sampleapp

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

class Adapter : RecyclerView.Adapter<Adapter.ItemViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        return ItemViewHolder(layoutInflater.inflate(R.layout.item_layout, parent, false))
    }

    override fun getItemCount(): Int = 100

    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) = Unit

    class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
Adapter.kt

Preparations Done!

Now running the app should give us a nice looking list of cards.

The uneven spacing issue

Oh, but it seems the space between cards is more than the top card and containers top.

list with uneven spacing

We have two ways to fix this.

  1. Change the item layout to have startMargin and endMargin to 16dp and give the card either of the top or bottom margin. In this case, also we need to add some padding to the RecyclerView, either to the top/bottom.
  2. Another way is to add top and bottom padding to the RecyclerView. This way is better since it keeps the symmetry in the item view, and you don't have to remember that you gave the card top margin or the bottom margin.

I'm going to go with the second way. There might be other ways to do this. Please let me know if you find any other.

After adding paddingTop and paddingBottom to the RecyclerView, rerun the app.

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
activity_main.xml

It results in the following screen:

It does look right now. But wait! When you scroll, you can see the gap between the toolbar and the first card.

The weird spacing issue

Also, there is space between the bottom card and the parent, and when you scroll, the scrim looks not so good.

list with weird spacing

The reason

RecyclerView is a ViewGroup, and by default, a ViewGroup clips it's children for padding, or in other words, it won't let the children view draw in the padding area.

We can change this behavior easily by adding clipToPadding to the RecyclerView.

If we set clipToPadding to false, RecyclerView allows the cards to be drawn in the padding area. Now the RecyclerView becomes:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
activity_main.xml

Rerun the app, and you see the magic!

Perfect Screen!

Summary

We used the attribute clipToPadding to create better-looking RecyclerView.