Nothing complicated.One additional overrided method and one additional layout. Now deeper.I will make a calendar of birthdays of Russian poets and writers. First you need three xml markup. Main screen and two holders: header and data.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    tools:context=".MainActivity"
>
    
    <android.support.v7.widget.RecyclerView 
        android:id="@+id/mainRecycler"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        app:layoutManager="android.support.v7.widget.LinearLayoutManager"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        tools:listitem="@layout/item_data" 
    />
    
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
>
    
    <TextView 
        android:id="@+id/text" 
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:background="@android:color/holo_blue_dark"
        android:paddingStart="10dp" 
        android:paddingTop="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp" 
        android:textColor="@android:color/white"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" 
        tools:text="Header" 
    />
    
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
>
    
    <TextView 
        android:id="@+id/date" 
        android:layout_width="wrap_content"
        android:layout_height="match_parent" 
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp" 
        android:layout_marginBottom="10dp"
        android:textColor="@android:color/darker_gray"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:text="date" 
    />
    
    <TextView 
        android:id="@+id/name" 
        android:layout_width="wrap_content"
        android:layout_height="match_parent" 
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@id/date"
        tools:text="name" 
    />
    
    <TextView 
        android:id="@+id/id" 
        android:layout_width="wrap_content"
        android:layout_height="match_parent" 
        android:layout_marginTop="1dp"
        android:layout_marginEnd="1dp" 
        android:textColor="@android:color/darker_gray"
        android:textSize="10sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        tools:text="id" 
    />
    
</android.support.constraint.ConstraintLayout>

Also we need data-classes for each datatype and its parent class:

package com.criticalgnome.recyclerwithtwoholders

abstract class MainItem
package com.criticalgnome.recyclerwithtwoholders

data class ItemHeader(
        val text: String
): MainItem()
package com.criticalgnome.recyclerwithtwoholders

import java.util.*

data class ItemData(
        val id: Long, 
        val date: Calendar, 
        val name: String
) : MainItem()

Now warming up adapter:

class MainAdapter(private val items: List<MainItem>, private val callback: Callback) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = when (viewType) {
        TYPE_DATA -> DataHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_data, parent, false))
        else -> HeaderHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_header, parent, false))
    }

    override fun getItemCount() = items.size

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is HeaderHolder -> holder.bind(items[position] as ItemHeader)
            is DataHolder -> holder.bind(items[position] as ItemData)
        }
    }

    override fun getItemViewType(position: Int) = when (items[position]) {
        is ItemData -> TYPE_DATA
        else -> TYPE_HEADER
    }

    inner class HeaderHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val headerText = itemView.findViewById<TextView>(R.id.text)
        fun bind(item: ItemHeader) {
            headerText.text = item.text itemView . setOnClickListener { callback.onItemClicked(item) }
        }
    }

    inner class DataHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val dataDate = itemView.findViewById<TextView>(R.id.date)
        private val dataName = itemView.findViewById<TextView>(R.id.name)
        private val dataId = itemView.findViewById<TextView>(R.id.id)
        fun bind(item: ItemData) {
            dataDate.text = StringBuilder("")
                    .append(if (item.date[Calendar.DAY_OF_MONTH] < 10) "0${item.date[Calendar.DATE]} " else "${item.date[Calendar.DAY_OF_MONTH]} ").append(
                            when (item.date[Calendar.MONTH]) {
                                0 -> "JAN"
                                1 -> "FEB"
                                2 -> "MAR"
                                3 -> "APR"
                                4 -> "MAY"
                                5 -> "JUN"
                                6 -> "JUL"
                                7 -> "AUG"
                                8 -> "SEP"
                                9 -> "OCT"
                                10 -> "NOV"
                                11 -> "DEC"
                                else -> ""
                            })
                    .append(" ${item.date[Calendar.YEAR]}")
            dataName.text = item.name
            dataId.text = item.id.toString()
            itemView.setOnClickListener { callback.onItemClicked(item) }
        }
    }

    interface Callback {
        fun onItemClicked(item: MainItem)
    }

    companion object {
        private const val TYPE_HEADER = 1 
        private const val TYPE_DATA = 2
    }
}

Drop some data in MainActivity.kt and run:

class MainActivity : AppCompatActivity() {

    private var id = 0L

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView (R.layout.activity_main)
        
        val items = listOf(
                ItemHeader("Январь"),
                ItemData(getId(), getCalendar(10, Calendar.JANUARY, 1883), "Алексей Николаевич Толстой"),
                ItemData(getId(), getCalendar(29, Calendar.JANUARY, 1860), "Антон Павлович Чехов"),
                ItemHeader("Февраль"),
                ItemData(getId(), getCalendar(10, Calendar.FEBRUARY, 1890), "Борис Леонидович Пастернак"),
                ItemData(getId(), getCalendar(16, Calendar.FEBRUARY, 1831), "Николай Семёнович Лесков"),
                ItemHeader("Март"),
                ItemData(getId(), getCalendar(28, Calendar.MARCH, 1868), "Максим Горький"),
                ItemHeader("Апрель"),
                ItemData(getId(), getCalendar(12, Calendar.APRIL, 1823), "Александр Николаевич Островский"),
                ItemHeader("Июнь"),
                ItemData(getId(), getCalendar(6, Calendar.JUNE, 1799), "Александр Сергеевич Пушкин"),
                ItemData(getId(), getCalendar(23, Calendar.JUNE, 1889), "Анна Андреевна Ахматова"),
                ItemHeader("Июль"),
                ItemData(getId(), getCalendar(19, Calendar.JULY, 1893), "Владимир Владимирович Маяковский"),
                ItemData(getId(), getCalendar(27, Calendar.JULY, 1853), "Владимир Галактионович Короленко"),
                ItemHeader("Сентябрь"),
                ItemData(getId(), getCalendar(9, Calendar.SEPTEMBER, 1828), "Лев Николаевич Толстой"),
                ItemHeader("Октябрь"),
                ItemData(getId(), getCalendar(3, Calendar.OCTOBER, 1895), "Сергей Александрович Есенин"),
                ItemData(getId(), getCalendar(7, Calendar.OCTOBER, 1870), "Александр Иванович Куприн"),
                ItemData(getId(), getCalendar(15, Calendar.OCTOBER, 1814), "Михаил Юрьевич Лермонтов"),
                ItemData(getId(), getCalendar(22, Calendar.OCTOBER, 1870), "Иван Алексеевич Бунин"),
                ItemHeader("Ноябрь"),
                ItemData(getId(), getCalendar(9, Calendar.NOVEMBER, 1818), "Иван Сергеевич Тургенев"),
                ItemData(getId(), getCalendar(11, Calendar.NOVEMBER, 1821), "Фёдор Михайлович Достоевский"),
                ItemData(getId(), getCalendar(28, Calendar.NOVEMBER, 1880), "Александр Александрович Блок"),
                ItemHeader("Декабрь"),
                ItemData(getId(), getCalendar(5, Calendar.DECEMBER, 1803), "Фёдор Иванович Тютчев"),
                ItemData(getId(), getCalendar(5, Calendar.DECEMBER, 1820), "Афанасий Афанасьевич Фет"),
                ItemData(getId(), getCalendar(10, Calendar.DECEMBER, 1821), "Николай Алексеевич Некрасов"),
                ItemData(getId(), getCalendar(13, Calendar.DECEMBER, 1873), "Валерий Яковлевич Брюсов"))

        val mainAdapter = MainAdapter(items, object : MainAdapter.Callback {
            
            override fun onItemClicked(item: MainItem) {
                when (item) {
                    is ItemHeader -> Toast.makeText(this@MainActivity, item.text, Toast.LENGTH_SHORT).show()
                    is ItemData -> Toast.makeText(this@MainActivity, item.name, Toast.LENGTH_SHORT).show()
                }
            }
        })
        mainRecycler.adapter = mainAdapter
    }

    private fun getCalendar(date: Int, month: Int, year: Int): Calendar {
        val calendar = Calendar.getInstance()
        calendar.set(year, month, date)
        return calendar
    }

    private fun getId() = id++
}

All code, as always, on my github.

Leave a Reply

Close Menu