ListView Section Header Kotlin Android Example | Group by Header

listview section header kotlin, kotlin pick video from gallery or capture from camera, kotlin custom spinner with image, pull to refresh listview android, swipe to refresh recyclerview android, expandablelistview in kotlin, Kotlin Horizontal Progressbar Android, kotlin image slider from url, Kotlin GIF Animated Splash Screen, Kotlin RecyclerView Sectioned Header, kotlin indeterminate circular progressbar, android dexter kotlin, kotlin digital signature view, kotlin alertdialog with edittext, elasticsearch windows, android dexter kotlin

Read about ListView Section Header Kotlin Android Example Tutorial.

We will make listview Group by Header means that listview items will be sorted by the header.

Section header means that a header among listview items to sort them with particular category.

For example, you are making listview with various names of counties. We can categorize countries by their continents.

So, you will make the first row as a section header which have continent name like Asia. Then in the second, third row you will write Asian countries like India, Chine etc.

After Asia, again you will make listview row as a section header and will name it Europe and further this process continues.

In our listview section header kotlin example, we will create a listview with the company names of different vehicles.

Here, we will insert a header to categorize the vehicles by it’a various types like Bikes, Cars, Air Crafts etc. For more reference, see the below video.

First of all, watch the below video to show the last results of the tutorial.

 

Step 1. View Layout Files

First of all, make a new project in the android studio with empty activity and kotlin as the main programming language.

We will create different layout view structure for both header and normal row of listview.

For this, we need to create two different layout files : one for header and another for normal row.

So make two xml files res->layout directory. Name of first file should be lv_child.xml and second file should have the name like lv_header.xml

Add the below source code in lv_child.xml file.

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="20dp"
        android:background="#e9771f"
        android:textColor="#ffffff"
        android:textSize="40sp"
        android:id="@+id/tvChild"
        android:text="Hello"/>

</android.support.constraint.ConstraintLayout>

This file will generate the view layout for all the normal listview rows.

There is only one text view in this file, so it will show the vehicle company names.

Following is the source block for lv_header.xml

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="20dp"
        android:background="#e91fce"
        android:textColor="#13cac7"
        android:textSize="40sp"
        android:id="@+id/tvVehicle"
        android:text="Hello"/>

</LinearLayout>

Similar to the child layout, above file will generate the layout structure for the header row.

This file also have only one text view but have different background color so that we can easily identify the difference between header and regular row of the listview.

We will use both these view files in the adapter class later.

Step 2. Two Model Classes For Header and Child rows

Make a new kotlin class and give it a name like HeaderModel.kt

Write down the following lines in HeaderModel.kt

class HeaderModel : MainActivity.ListItem {

    private lateinit var name : String

    fun setheader(header: String) {
        this.name = header
    }

    override
    fun isHeader () : Boolean {
        return true
    }

    override
    fun getName(): String {
        return name
    }
}

This file will help us to write header names in the row of the listview.

It includes three methods. A method setheader() will set the header name, isHeader() will tell us whether the row is header row or regular row.

getName() will simply return the name of the header (Vehicle type).

Now create another kotlin file and it’s name would be ChildModel.kt

Below is the coding writings for ChildModel.kt file.

class ChildModel : MainActivity.ListItem {

    private lateinit var name: String

    override
    fun isHeader () : Boolean {
        return false
    }

    override
    fun getName(): String {
        return name
    }

    fun setChild(child: String) {
        this.name = child
    }
}

Child model is almost similar to header model.

It also has three methods with it’s purposes similar to header. Only difference is, it will set and return child name instead of header name (Vehicle company).

Step 3. Perfect Adapter Class

We need to create adapter class which will help us to maintain data structure in list view.

Make a new Kotlin class with the name like CustomeAdapter.kt and write the following lines in it

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import java.util.ArrayList

class CustomeAdapter(private val context: Context, private val listItemArrayList: ArrayList<MainActivity.ListItem>) :
    BaseAdapter() {

    override fun getViewTypeCount(): Int {
        return count
    }

    override fun getItemViewType(position: Int): Int {

        return position
    }

    override fun getCount(): Int {
        return listItemArrayList.size
    }

    override fun getItem(position: Int): Any {
        return listItemArrayList[position]
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
        var convertView = convertView
        val holder: ViewHolder

        if (convertView == null) {
            holder = ViewHolder()
            val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

            if (listItemArrayList[position].isHeader()) {
                convertView = inflater.inflate(R.layout.lv_header, null, true)
                holder.tvLabel = convertView!!.findViewById(R.id.tvVehicle) as TextView
            } else {
                convertView = inflater.inflate(R.layout.lv_child, null, true)
                holder.tvLabel = convertView!!.findViewById(R.id.tvChild) as TextView
            }

            convertView.tag = holder
        } else {
            // the getTag returns the viewHolder object set as a tag to the view
            holder = convertView.tag as ViewHolder
        }

        holder.tvLabel!!.text = listItemArrayList[position].getName()

        return convertView
    }

    private inner class ViewHolder {

        var tvLabel: TextView? = null

    }

}

This adapter class will create the every row of the listview. For this, it will inflate the view files and then it will set the value in the text views.

See the below source code

  if (listItemArrayList[position].isHeader()) {
                convertView = inflater.inflate(R.layout.lv_header, null, true)
                holder.tvLabel = convertView!!.findViewById(R.id.tvVehicle) as TextView
            } else {
                convertView = inflater.inflate(R.layout.lv_child, null, true)
                holder.tvLabel = convertView!!.findViewById(R.id.tvChild) as TextView
            }

In this if else condition, compiler will first check whether the row is of header or not.

If it is header then it will inflate the lv_header.xml file otherwise it will inflate the lv_child.xml file.

Then it will initiate the text view.

Step 4. Last Code For Main Files

Now we have reached to the final step of this tutorial.

You should have two main file activity_main.xml and MainActivity.kt

In your activity_main.xml file, add the following lines

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <ListView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:id="@+id/listView"/>

</android.support.constraint.ConstraintLayout>

It has just one list view, nothing else.

Now in MainActivity.kt file, write the below coding lines

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ListView
import java.lang.String
import java.util.ArrayList

class MainActivity : AppCompatActivity() {

    private var lv: ListView? = null
    private var customeAdapter: CustomeAdapter? = null

    private val vehicleTypes = arrayOf("Cars", "Bikes", "Air Crafts", "Old Vehicles")

    private var listItemArrayList: ArrayList<ListItem>? = null

    private val childnames = arrayOf(
        "Range Rover",
        "Lamborghini",
        "Rolls Royce",
        "Ferrari",
        "Harley davidson",
        "Ducati",
        "BMW",
        "Honda",
        "Boeing",
        "Airbus",
        "Royal Air",
        "Space X",
        "Horse",
        "Elephant",
        "Camel",
        "Donkey"
    )

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

        lv = findViewById(R.id.listView) as ListView

        listItemArrayList = ArrayList()
        populateList()

        customeAdapter = CustomeAdapter(this, listItemArrayList!!)
        lv!!.setAdapter(customeAdapter)
    }

    interface ListItem {
         fun isHeader(): Boolean
         fun getName(): kotlin.String
    }

    private fun populateList() {

        var headerdone = 0
        var childdone = 0

        for (i in 0..19) {

            if (i == 0 || (i == 5) or (i == 10) or (i == 15)) {
                val vehicleModel = HeaderModel()
                vehicleModel.setheader(vehicleTypes[headerdone])
                listItemArrayList!!.add(vehicleModel)
                headerdone = headerdone + 1
            } else {
                val childModel = ChildModel()
                childModel.setChild(childnames[childdone])
                listItemArrayList!!.add(childModel)
                childdone = childdone + 1
            }
        }

    }

}

Read the below lines

 interface ListItem {
         fun isHeader(): Boolean
         fun getName(): kotlin.String
    }  

private var listItemArrayList: ArrayList<ListItem>? = null

    private val childnames = arrayOf(
        "Range Rover",
        "Lamborghini",
        "Rolls Royce",
        "Ferrari",
        "Harley davidson",
        "Ducati",
        "BMW",
        "Honda",
        "Boeing",
        "Airbus",
        "Royal Air",
        "Space X",
        "Horse",
        "Elephant",
        "Camel",
        "Donkey"
    )

There is an interface named ListItem with two functions : isHeader() and getName()

Then, there is an arrayList “listItemArrayList” which holds the objects of the interface “ListItem

String array named “childnames” will hold the names of the vehicle companies which are the normal list view rows.

See the following

 private val vehicleTypes = arrayOf("Cars", "Bikes", "Air Crafts", "Old Vehicles")

Above line is string array “vehiceTypes” which holds the header names.

Now see the below code block

  private fun populateList() {

        var headerdone = 0
        var childdone = 0

        for (i in 0..19) {

            if (i == 0 || (i == 5) or (i == 10) or (i == 15)) {
                val vehicleModel = HeaderModel()
                vehicleModel.setheader(vehicleTypes[headerdone])
                listItemArrayList!!.add(vehicleModel)
                headerdone = headerdone + 1
            } else {
                val childModel = ChildModel()
                childModel.setChild(childnames[childdone])
                listItemArrayList!!.add(childModel)
                childdone = childdone + 1
            }
        }

    }

A method populateList() will fill the objects into listItemArrayList which will work as the data source to populate the list view.

You can read this tutorial in JAVA language.

Click to read JAVA version of this tutorial.

Download Code For Listview Section Header Kotlin

Click to go to Github to download source code