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.