ExpandableListView In Kotlin Android Example Tutorial

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

Let us create ExpandableListView In Kotlin Android Example Tutorial.

In this example, we will create simple expandable listview using kotlin in android studio.

Expandable list view is useful when you have too many elements and you can categorize them.

For example, you can categorize various movies according to categories like Action, Comedy, Romantic etc.

We are going to make expandable listview for some movie names.

First of all, see the below video which shows you the final output of this example.

 

 

Now follow all the below steps to complete the tutorial.

Step 1. Parent and Child Layout

First of all, make a new project in android studio. Here, select Kotlin as the primary source language.

Every expandable listview consist two main things : parent rows and child rows.

In our example, movie category is parent row and movie name is child row.

We need to create separate XML layout files for both parent and child rows.

So go to app->res->layout folder directory and make a new XML file.

You should set the name of this XML file as parent_layout.xml

Below are the source code lines for parent_layout.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"
    android:divider="#ec2121"
    android:dividerHeight="0.5dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
        android:textColor="#f07e27"
        android:textSize="20sp"
        android:text="Parent"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:id="@+id/parent_txt" />

</LinearLayout>

There is only one Text View in the parent file.

Now in the same directory, make a new XML layout file and give it a name like child_layout.xml

Inside child_layout.xml you should write the following code

<?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:textColor="#07800d"
        android:textSize="20sp"
        android:text="child"
        android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:id="@+id/child_txt" />
</LinearLayout>

Similar to the parent file, above file also have only one text view.

You can add image and other widgets as per your requirements in both parent and child XML files.

Step 2. Adapter For Expandable ListView

Now let us create adapter class. For this make a new Kotlin class and give it a name as ExpandableAdapter.kt

Inside this ExpandableAdapter.kt class, add the following source structure

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

class ExpandableAdapter(
    internal var ctx: Context,
    childList: ArrayList<ArrayList<String>>,
    private val parents: Array<String>
) : BaseExpandableListAdapter() {

    init {
        childLists = childList

    }

    override fun getGroupCount(): Int {
        return childLists.size
    }

    override fun getChildrenCount(parent: Int): Int {
        return parents.size
    }

    override fun getGroup(parent: Int): Any {

        return parents[parent]
    }

    override fun getChild(parent: Int, child: Int): Any {
        return childLists[parent][child]
    }

    override fun getGroupId(parent: Int): Long {
        return parent.toLong()
    }

    override fun getChildId(parent: Int, child: Int): Long {
        return child.toLong()
    }

    override fun hasStableIds(): Boolean {
        return false
    }

    override fun getGroupView(parent: Int, isExpanded: Boolean, convertView: View?, parentview: ViewGroup): View {
        var convertView = convertView

        if (convertView == null) {
            val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.parent_layout, parentview, false)

        }

        val parent_textvew = convertView!!.findViewById(R.id.parent_txt) as TextView
        parent_textvew.text = parents[parent]
        return convertView
    }

    override fun getChildView(
        parent: Int,
        child: Int,
        isLastChild: Boolean,
        convertView: View?,
        parentview: ViewGroup
    ): View {
        var convertView = convertView

        if (convertView == null) {
            val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.child_layout, parentview, false)

        }

        val child_textvew = convertView!!.findViewById(R.id.child_txt) as TextView
        child_textvew.text = getChild(parent, child).toString()
        return convertView
    }

    override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean {
        return false
    }

    companion object {
        lateinit var childLists: ArrayList<ArrayList<String>>
    }
}

Adapter class will get the data inside it’s constructor and then it set the data in parent as well row item.

There are two different methods to set data in parent and child rows.

See the below lines from getGroupView() method.

   override fun getGroupView(parent: Int, isExpanded: Boolean, convertView: View?, parentview: ViewGroup): View {
        var convertView = convertView

        if (convertView == null) {
            val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.parent_layout, parentview, false)

        }

        val parent_textvew = convertView!!.findViewById(R.id.parent_txt) as TextView
        parent_textvew.text = parents[parent]
        return convertView
    }

In this method, compiler will inflate the XML layout file parent_layout.xml

Then it will find the text view using findViewById() method. After this, compiler will set the value of the text view using parents variable.

Read the following lines of getChildView() method.

 override fun getChildView(
        parent: Int,
        child: Int,
        isLastChild: Boolean,
        convertView: View?,
        parentview: ViewGroup
    ): View {
        var convertView = convertView

        if (convertView == null) {
            val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = inflater.inflate(R.layout.child_layout, parentview, false)

        }

        val child_textvew = convertView!!.findViewById(R.id.child_txt) as TextView
        child_textvew.text = getChild(parent, child).toString()
        return convertView
    }

Here, compiler will inflate child_layout.xml file. Then similar to getGroupView() method, it will find the text view.

And at last, it will simply set the value of the text view.

Step 3. Last Modification

You should find two files which are automatically generated when you created the new project in the android studio.

One file is activity_main.xml and another is MainActivity.kt

You need to insert the below snippet inside the activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        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">

    <ExpandableListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/exp_list"
            android:indicatorLeft="?android:attr/expandableListPreferredItemIndicatorLeft"
            android:divider="#A4C739"
            android:dividerHeight="0.5dp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"/>

</LinearLayout>

Main XML layout file contain only one element which is ExpandableListView.

Now below is the source code snippet for MainActivity.kt file.

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ExpandableListView
import java.util.ArrayList

class MainActivity : AppCompatActivity() {

    private var expandableAdapter: ExpandableAdapter? = null
    private var expList: ExpandableListView? = null
    private val parents = arrayOf("Action Movies", "Romantic Movies", "Comedy Movies")
    private var Action_Movies: ArrayList<String>? = null
    private var Romantic_Movies: ArrayList<String>? = null
    private var Comedy_Movies: ArrayList<String>? = null

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

        expList = findViewById(R.id.exp_list) as ExpandableListView

        setChildMovies()

        expandableAdapter = ExpandableAdapter(this, childList, parents)
        expList!!.setAdapter(expandableAdapter)

    }

    private fun setChildMovies() {

        Action_Movies = ArrayList()
        Romantic_Movies = ArrayList()
        Comedy_Movies = ArrayList()

        Action_Movies!!.add("Dark Knight")
        Action_Movies!!.add("Transporter")
        Action_Movies!!.add("Iron Man")

        Romantic_Movies!!.add("Twilight")
        Romantic_Movies!!.add("Titanic")
        Romantic_Movies!!.add("The House Bunny")

        Comedy_Movies!!.add("We are the millers")
        Comedy_Movies!!.add("Hang over")
        Comedy_Movies!!.add("Last Night")

        childList = ArrayList()

        childList.add(Action_Movies!!)
        childList.add(Romantic_Movies!!)
        childList.add(Comedy_Movies!!)


    }

    companion object {
        lateinit var childList: ArrayList<ArrayList<String>>
    }

}

More Information

Now let us see lines of MainActivity.kt class in detail.

First of all, read the following code

  private var expandableAdapter: ExpandableAdapter? = null
    private var expList: ExpandableListView? = null
    private val parents = arrayOf("Action Movies", "Romantic Movies", "Comedy Movies")
    private var Action_Movies: ArrayList<String>? = null
    private var Romantic_Movies: ArrayList<String>? = null
    private var Comedy_Movies: ArrayList<String>? = null

First line will create the object of the ExpandableAdapter class. Second will give us the object of ExpandableListView class.

Third line will create one string array. This array will hold three string values : “Action Movies”, “Romantic Movies” and “Comedy Movies”

Fourth, fifth and sixth lines will create one Arraylist with String type.

Now look inside the onCreate() method. There is a method named setChildMovies() is there.

Below is the code block for setChildMovies() method.

 private fun setChildMovies() {

        Action_Movies = ArrayList()
        Romantic_Movies = ArrayList()
        Comedy_Movies = ArrayList()

        Action_Movies!!.add("Dark Knight")
        Action_Movies!!.add("Transporter")
        Action_Movies!!.add("Iron Man")

        Romantic_Movies!!.add("Twilight")
        Romantic_Movies!!.add("Titanic")
        Romantic_Movies!!.add("The House Bunny")

        Comedy_Movies!!.add("We are the millers")
        Comedy_Movies!!.add("Hang over")
        Comedy_Movies!!.add("Last Night")

        childList = ArrayList()

        childList.add(Action_Movies!!)
        childList.add(Romantic_Movies!!)
        childList.add(Comedy_Movies!!)


    }

Above method will create the names of the movies and it will store it inside arraylist.

First three lines will initialize three arraylists for each category (Action_Movies, Romantic_Movies, Comedy_Movies).

Then fifth, sixth and seventh lines will add three action movies in the first arraylist.

Similarly, eight, ninth and tenth lines will add three romantic movies in second arraylist and eleventh, twelfth and thirteenth lines will insert three comedy movies inside third arraylist.

Then compiler will initialize new arraylist whose name is childList.

Inside this childList , compiler will add all three arraylists (Action_Movies, Romantic_Movies, Comedy_Movies).

Now see the following two code lines from onCreate() method.

 expandableAdapter = ExpandableAdapter(this, childList, parents)
        expList!!.setAdapter(expandableAdapter)

First line will initialize the object of the ExpandableAdapter class and second line will set the adapter object in the expandable listview object.

You can download the whole source code from Github by using the link given at the bottom end.

If you want to create expandable listview in JAVA language then read below tutorial.

In JAVA : Android Expandable ListView Example Tutorial

Download Code For ExpandableListView In Kotlin

https://github.com/demonuts/ExpandableListView-In-Kotlin-Android-Example-Tutorial