How to Create a Sticky Header in Jetpack Compose

Table of Contents

If you’ve ever scrolled through a long list in an app and noticed that the section title stays pinned at the top until the next section appears, you’ve seen a sticky header. Sticky headers make lists easier to navigate, especially when content is grouped by category.

In this post, we’ll learn step by step how to implement a Sticky Header in Jetpack Compose using LazyColumn. Don’t worry if you’re just getting started with Compose—the explanation will stay simple, with code examples and clear breakdowns.

What is a Sticky Header?

A sticky header is a UI element that remains visible at the top of a scrolling list while the content beneath it scrolls. It’s often used in apps like Contacts (where the alphabet letters stick as you scroll) or e-commerce apps (where categories like “Shoes,” “Bags,” or “Clothing” stay pinned).

Jetpack Compose makes this much easier to implement compared to the old RecyclerView approach in XML.

Why Use Sticky Headers in Jetpack Compose?

Adding a Sticky Header in Jetpack Compose improves:

  • Readability: Users instantly know which section they’re in.
  • Navigation: Helps users scan through grouped content quickly.
  • User Experience: Feels modern, polished, and professional.

The Key Composable: stickyHeader

Jetpack Compose provides a built-in modifier inside LazyColumn called stickyHeader. This allows you to define a composable item that “sticks” to the top while scrolling.

Basic Code Example

Here’s a simple example of creating a Sticky Header in Jetpack Compose:

Kotlin
@Composable
fun StickyHeaderList() {
    val groupedItems = mapOf(
        "Fruits" to listOf("Apple", "Banana", "Mango", "Orange"),
        "Vegetables" to listOf("Carrot", "Potato", "Tomato"),
        "Drinks" to listOf("Water", "Juice", "Soda")
    )

    LazyColumn {
        groupedItems.forEach { (header, items) ->
            stickyHeader {
                Text(
                    text = header,
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(Color.LightGray)
                        .padding(16.dp),
                    fontWeight = FontWeight.Bold
                )
            }

            items(items) { item ->
                Text(
                    text = item,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(12.dp)
                )
            }
        }
    }
}

Let’s break it down so it’s crystal clear:

Grouped Data

  • We created a Map with categories as keys ("Fruits", "Vegetables", "Drinks") and a list of items under each.

LazyColumn

  • Works like a RecyclerView but in Compose. It’s efficient for large lists.

stickyHeader

  • This is the magic. Whatever you put inside stickyHeader will remain stuck at the top until another header replaces it.
  • We used a Text with background color and padding so it looks like a section header.

items()

  • Displays each element in the list under its header.

Styling the Sticky Header

You don’t want your sticky header to look boring. Here are a few tweaks you can add:

Kotlin
stickyHeader {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        color = Color.DarkGray,
        shadowElevation = 4.dp
    ) {
        Text(
            text = header,
            modifier = Modifier.padding(16.dp),
            color = Color.White,
            fontSize = 18.sp,
            fontWeight = FontWeight.Bold
        )
    }
}

This adds:

  • Background color (DarkGray)
  • Shadow elevation for depth
  • White text for contrast

When to Use Sticky Headers

Sticky headers are perfect for:

  • Contact lists grouped alphabetically
  • Shopping apps with categories
  • News apps with sections (e.g., Sports, Tech, Business)
  • Music playlists grouped by artist or album

Common Mistakes to Avoid

  • Too many sticky headers: Don’t overuse them — it can feel cluttered.
  • No visual distinction: Make sure headers look different from list items.
  • Performance issues: For extremely large datasets, consider lazy loading.

Conclusion

Creating a Sticky Header in Jetpack Compose is simple, thanks to the stickyHeader API inside LazyColumn. With just a few lines of code, you can build a smooth, user-friendly list that looks polished and professional.

As Compose continues to evolve, features like these make UI development faster, cleaner, and more intuitive. Whether you’re building a contacts app, a shopping app, or just experimenting, sticky headers will give your lists a better structure and improve the user experience.

Pro Tip: Always test on different screen sizes to make sure your headers remain clear and readable.

Now it’s your turn — try adding a sticky header to your own Jetpack Compose project and see the difference!

Skill Up: Software & AI Updates!

Receive our latest insights and updates directly to your inbox

Related Posts

error: Content is protected !!