Skip to main content

How to implement section headers in a RecyclerView in Kotlin Android

How to implement section headers in a RecyclerView in Kotlin Android.

Here's a step-by-step tutorial on how to implement section headers in a RecyclerView in Kotlin for Android:

Step 1: Set up your project

Create a new Android project in Android Studio. Make sure you have the necessary dependencies for RecyclerView in your app's build.gradle file:

implementation 'androidx.recyclerview:recyclerview:1.2.1'

Step 2: Create a data model

Create a data model that represents the items in your RecyclerView. For this tutorial, let's assume we have a list of items with a name and a section:

data class Item(val name: String, val section: String)

Step 3: Create the RecyclerView adapter

Create a new Kotlin class for your RecyclerView adapter. Extend it from RecyclerView.Adapter and create a ViewHolder class to hold the views for each item:

class MyAdapter(private val items: List<Item>) :
RecyclerView.Adapter<MyAdapter.ViewHolder>() {

// ViewHolder class to hold the views for each item
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val nameTextView: TextView = view.findViewById(R.id.nameTextView)
val sectionTextView: TextView = view.findViewById(R.id.sectionTextView)
}

// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_layout, parent, false)
return ViewHolder(view)
}

// Replace the contents of a view (invoked by the layout manager)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
holder.nameTextView.text = item.name
holder.sectionTextView.text = item.section
}

// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = items.size
}

Step 4: Create the layout for each item

Create a layout file for each item in your RecyclerView. In this example, we'll create a file called item_layout.xml with two TextViews for the item name and section:

<!-- item_layout.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<TextView
android:id="@+id/nameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />

<TextView
android:id="@+id/sectionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp" />

</LinearLayout>

Step 5: Create the layout for the section header

Create a layout file for the section header in your RecyclerView. In this example, we'll create a file called header_layout.xml with a single TextView:

<!-- header_layout.xml -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />

Step 6: Modify the adapter to support section headers

Modify the adapter to support section headers. You can achieve this by overriding the getItemViewType method to return a different view type for the section headers, and then inflating the appropriate layout in the onCreateViewHolder method:

class MyAdapter(private val items: List<Item>) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {

// ViewHolder class for items
class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val nameTextView: TextView = view.findViewById(R.id.nameTextView)
val sectionTextView: TextView = view.findViewById(R.id.sectionTextView)
}

// ViewHolder class for section headers
class HeaderViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val sectionTextView: TextView = view.findViewById(R.id.sectionTextView)
}

// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == TYPE_ITEM) {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_layout, parent, false)
ItemViewHolder(view)
} else {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.header_layout, parent, false)
HeaderViewHolder(view)
}
}

// Replace the contents of a view (invoked by the layout manager)
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position]

if (holder is ItemViewHolder) {
holder.nameTextView.text = item.name
holder.sectionTextView.text = item.section
} else if (holder is HeaderViewHolder) {
holder.sectionTextView.text = item.section
}
}

// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = items.size

// Return the view type of the item at the specified position
override fun getItemViewType(position: Int): Int {
val item = items[position]
return if (item.section == "Section 1") {
TYPE_HEADER
} else {
TYPE_ITEM
}
}

companion object {
private const val TYPE_HEADER = 0
private const val TYPE_ITEM = 1
}
}

Step 7: Create the RecyclerView in your activity

In your activity, create an instance of the RecyclerView, set its layout manager, and set the adapter:

class MainActivity : AppCompatActivity() {

private lateinit var recyclerView: RecyclerView

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

recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)

val items = listOf(
Item("Item 1", "Section 1"),
Item("Item 2", "Section 1"),
Item("Item 3", "Section 2"),
Item("Item 4", "Section 2"),
Item("Item 5", "Section 2")
)

val adapter = MyAdapter(items)
recyclerView.adapter = adapter
}
}

And that's it! You have now implemented section headers in a RecyclerView in Kotlin for Android. Run your app to see the RecyclerView with the section headers and items.

Feel free to customize the layout files and adapter logic to fit your specific needs.