Skip to main content
Android UI Design with Kotlin
CHAPTER 09 Beginner

RecyclerView and Beautiful List Design

Updated: May 31, 2026
6 min read

# CHAPTER 9

RecyclerView and Beautiful List Design

1. Introduction

Modern applications are driven by data: a feed of photos, a list of messages, or a grid of products. Early on, Android used a component called ListView to display lists, but it was inefficient and prone to lagging when scrolling through thousands of items. Enter RecyclerView. It is an incredibly powerful, highly optimized widget designed to display massive data sets smoothly. In this chapter, we will master the RecyclerView and design beautiful, custom list items.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand the architecture of RecyclerView and the Adapter pattern.
  • Implement the ViewHolder pattern to optimize performance.
  • Use LayoutManagers to display data in linear lists or grids.
  • Design a custom XML layout for a single list item.
  • Build a real-world Social Feed UI.

3. How RecyclerView Works

The magic of RecyclerView is in its name: it recycles views. If you have 1,000 items in your list, but only 5 fit on the screen at a time, RecyclerView only creates about 7 or 8 views in memory. When you scroll up and an item disappears off the top of the screen, that view is *recycled*, its data is swapped out for the new item coming in from the bottom, and it is reused.

Core Components:

  1. 1. RecyclerView: The UI widget itself that gets placed in your layout.
  1. 2. LayoutManager: Dictates *how* the items are arranged (Vertical, Horizontal, or Grid).
  1. 3. Adapter: The bridge between your raw data (like a List of strings) and the RecyclerView.
  1. 4. ViewHolder: Holds the references to the UI elements (TextViews, ImageViews) for a single item, preventing expensive findViewById calls during scrolling.

4. Custom Item UI Design

Before writing Kotlin code, you must design how a *single* item in your list will look. You do this by creating a brand new XML layout file.

Let's design a custom item for a Social Feed: item_post.xml.

xml
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView
    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="wrap_content"
    android:layout_margin="8dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="2dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <!-- User Avatar -->
        <ImageView
            android:id="@+id/avatarImage"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:background="#E0E0E0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <!-- User Name -->
        <TextView
            android:id="@+id/usernameText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="John Doe"
            android:textStyle="bold"
            android:layout_marginStart="12dp"
            app:layout_constraintStart_toEndOf="@+id/avatarImage"
            app:layout_constraintTop_toTopOf="@+id/avatarImage" />

        <!-- Post Time -->
        <TextView
            android:id="@+id/timeText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="2 hours ago"
            android:textSize="12sp"
            app:layout_constraintStart_toStartOf="@+id/usernameText"
            app:layout_constraintTop_toBottomOf="@+id/usernameText" />

        <!-- Post Content -->
        <TextView
            android:id="@+id/contentText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Loving the new RecyclerView tutorial! #AndroidDev"
            android:layout_marginTop="16dp"
            app:layout_constraintTop_toBottomOf="@+id/avatarImage"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

5. Layout Managers

The LayoutManager is completely decoupled from the data. You can change how the entire list looks with one line of code!
  • LinearLayoutManager: Standard vertical or horizontal scrolling list.
  • GridLayoutManager: A grid with a specific number of columns (e.g., 2 columns for a photo gallery).
  • StaggeredGridLayoutManager: A grid where items can have different heights (like Pinterest).

6. Mini Project: Implementing the Adapter

Here is a simplified Kotlin structure for the Adapter that connects your data to the item_post.xml.
kotlin
12345678910111213141516171819202122232425
// 1. Create the Adapter class
class PostAdapter(private val postList: List<String>) : RecyclerView.Adapter<PostAdapter.PostViewHolder>() {

    // 2. Create the ViewHolder
    class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val contentText: TextView = itemView.findViewById(R.id.contentText)
    }

    // 3. Inflate the XML layout for each item
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_post, parent, false)
        return PostViewHolder(view)
    }

    // 4. Bind the data to the views
    override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
        val currentPost = postList[position]
        holder.contentText.text = currentPost
    }

    // 5. Return the total number of items
    override fun getItemCount(): Int {
        return postList.size
    }
}

7. Design Principles

  • Touch Targets: Ensure buttons or clickable areas inside your list items are at least 48dp x 48dp.
  • Visual Separation: Use dividers, margins, or CardView elevations to clearly separate one list item from the next.
  • Asynchronous Loading: If your list items contain images, use libraries like Glide to load them in the background. Loading large images on the main thread inside onBindViewHolder will cause terrible scrolling lag.

8. Common Mistakes

  • wrapcontent for layoutheight on RecyclerView: Always set the RecyclerView height to matchparent or 0dp (in ConstraintLayout). Setting it to wrapcontent forces Android to measure all items at once, destroying the recycling performance benefit.
  • matchparent for layoutheight in the Item XML: If your itempost.xml has a height of matchparent, every single item will take up the entire screen! Always use wrapcontent for the height of your item layout's root element.

9. Best Practices

  • Use DiffUtil instead of notifyDataSetChanged() when updating your list data to get beautiful, automatic animations when items are added or removed.

10. Exercises

  1. 1. Modify the itempost.xml to include a "Like" button (a heart Vector Asset) at the bottom right of the card.
  1. 2. In your Kotlin code, change the LinearLayoutManager to a GridLayoutManager with 2 columns and observe how the UI adapts.

11. UI Design Challenges

Challenge: Design a custom item layout for a "Chat App". It should have the profile picture on the left, the contact's name at the top right, a snippet of the latest message below the name, and the time of the message aligned to the far right edge.

12. MCQ Quiz with Answers

Question 1

What is the primary performance benefit of using a RecyclerView over a ListView?

Question 2

Which component determines whether a RecyclerView displays as a vertical list or a grid?

13. Interview Questions

  • Q: Explain the role of the ViewHolder in a RecyclerView.Adapter.
  • Q: Why should the root element of your item layout XML almost always have layoutheight="wrapcontent"?
  • Q: How does StaggeredGridLayoutManager differ from GridLayoutManager?

14. FAQs

Q: Can I have multiple different types of UI layouts in a single RecyclerView (e.g., text posts and image posts)? A: Yes! You can override getItemViewType(position: Int) in your adapter to return different integers based on the data type, and then inflate different XML layouts inside onCreateViewHolder based on that type.

15. Summary

RecyclerView is the backbone of almost every modern Android application. By separating the data management (Adapter), the view caching (ViewHolder), and the layout logic (LayoutManager), we can build infinitely scrolling, buttery-smooth feeds and grids. We successfully designed a Material Card for a social feed and explored how to connect it.

16. Next Chapter Recommendation

Our lists are functional and good-looking, but do they conform to industry standards? In Chapter 10: Material Design Principles, we will take a step back from the code to deeply understand Google's design language, exploring color palettes, typography, and elevation.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·