Android ExpandableListView Using Kotlin With Example

Greetings!
We have recently published 100+ articles on android tutorials with kotlin and java. If you need, you may visit Android Tutorial for beginners page. You can also check Kotlin Tutorial for beginners. Also, if you are interested in content writing, you can mail us at tutorialwing@gmail.com.
Hello Readers! In this post, we are going to learn about android ExpandableListView using kotlin in any android application. We will see how to use BaseExpandableListAdapter in ExpandableListView to show data in it. how to set groupExpandListener, groupCollapsedListener and childClickListener in expandableListView.

Note – We have used another widget textView in this tutorial. So, you may visit our tutorial on android textView in Kotlin.

if you wish to know more, you may visit official link of – this widget.

Output

Tutorialwing android ExpandableListView using kotlin output

ExpandableListView Tutorial output

SourceCode (Kotlin)

Getting Started

Android ExpandableListView can be defined as below –

ExpandableListView is a View that shows vertically scrolling two-level list. In this view, first level groups can be expanded to show it’s children items. ExpandableListView also shows an icon beside each group to show it’s status i.e. whether it is expanded or collapsed.

Note – You can not use value wrap_content for android:layout_height attribute of ExpandableListView if parent’s size is also not strictly specified. For example, if you have used ExpandableListView inside ScrollView, you can not use wrap_content for android:layout_height because ScrollView can have any height.




Example of Android ExpandableListView Using Kotlin

Now, we will see an example that shows how to use this widget in any android application. At first, we will create an application. Then, we will use expandableListView in it.

1. Creating New Project in Kotlin

Follow steps below to create new project. Please ignore the steps if you have already created the project.

Step Description
1. Open Android Studio.
2. Go to File => New => New Project. Write application name as ExpandableListView. Then, check Include Kotlin Support and click next button.
3. Select minimum SDK you need. However, we have selected 21 as minimum SDK. Then, click next button
4. Then, select Empty Activity => click next => click finish.
5. You will get a newly created project successfully if you have followed steps properly.

2. Modify values folder

Open res/values/strings.xml file. Then, add below code into it.

<resources>
	<string name="app_name">ExpandableListView</string>
</resources>

3. Create View For Child Item in ExpandableListView

Since we need an xml file that contains ui for a child item in expandableListView. So, create an xml file in main/res/layout folder with name list_item.xml.

Now, open main/res/layout/list_item.xml file and add below code into this file.

<?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="wrap_content"
	android:orientation="vertical">

	<TextView
		android:id="@+id/expandedListItem"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:paddingBottom="10dp"
		android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
		android:paddingTop="10dp"/>

</LinearLayout>

We are showing only name of an item in expandableListView. So, there is only textView in list_item.xml file.

4. Create View For Group Item in ExpandableListView

Now, we need an ui for group item in expandableListView. So, create an xml file, named list_group.xml, in main/res/layout folder.

Then, open main/res/layout/list_group.xml file and add below code into it.

<?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:orientation="vertical">

	<TextView
		android:id="@+id/listTitle"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:paddingBottom="10dp"
		android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
		android:paddingTop="10dp"
		android:textColor="@android:color/black"/>

</LinearLayout>

In each group item, we are showing only name of the group. So, we need only textView in xml file.

Till now, we have defined ui for a group and child item. Now, we will use this xml file in adapter class that provides data to the expandableListView.




5. Create Adapter For ExpandableListView

Now, we will create adapter for expandableListView that will be used to provide data to the view. So, create a kotlin file , named CustomExpandableListAdapter.kt, in main/java/com.tutorialwing.expandablelistview package.

Now, open main/java/com.tutorialwing.expandablelistview/CustomExpandableListAdapter.kt file and add below code into it.

package com.tutorialwing.expandablelistview

import android.content.Context
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseExpandableListAdapter
import android.widget.TextView

import java.util.HashMap

class CustomExpandableListAdapter internal constructor(private val context: Context, private val titleList: List<String>, private val dataList: HashMap<String, List<String>>) : BaseExpandableListAdapter() {

    override fun getChild(listPosition: Int, expandedListPosition: Int): Any {
        return this.dataList[this.titleList[listPosition]]!![expandedListPosition]
    }

    override fun getChildId(listPosition: Int, expandedListPosition: Int): Long {
        return expandedListPosition.toLong()
    }

    override fun getChildView(listPosition: Int, expandedListPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View {
        var convertView = convertView
        val expandedListText = getChild(listPosition, expandedListPosition) as String
        if (convertView == null) {
            val layoutInflater = this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = layoutInflater.inflate(R.layout.list_item, null)
        }
        val expandedListTextView = convertView!!.findViewById<TextView>(R.id.expandedListItem)
        expandedListTextView.text = expandedListText
        return convertView
    }

    override fun getChildrenCount(listPosition: Int): Int {
        return this.dataList[this.titleList[listPosition]]!!.size
    }

    override fun getGroup(listPosition: Int): Any {
        return this.titleList[listPosition]
    }

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

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

    override fun getGroupView(listPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View {
        var convertView = convertView
        val listTitle = getGroup(listPosition) as String
        if (convertView == null) {
            val layoutInflater = this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = layoutInflater.inflate(R.layout.list_group, null)
        }
        val listTitleTextView = convertView!!.findViewById<TextView>(R.id.listTitle)
        listTitleTextView.setTypeface(null, Typeface.BOLD)
        listTitleTextView.text = listTitle
        return convertView
    }

    override fun hasStableIds(): Boolean {
        return false
    }

    override fun isChildSelectable(listPosition: Int, expandedListPosition: Int): Boolean {
        return true
    }
}

As we already know, this class provides data for an item to the expandableListView. We have inherited this class from BaseExpandableListAdapter class. A constructor has also been defined that accepts context, titleList and dataList. Then, we have overridden some of the methods in this class.

They are –

S. No. Method Description
1. getChild() It returns the data associated with child at given child position (i.e. expandedListPosition) in a given group (i.e. listPosition) . Actual method is getChild(listPosition: Int , expandedListPosition: Int): Any .
2. getChildId() Returns id of the child at given child position (i.e. expandedListPosition) within group at given position (i.e. listPosition) . Actual method is getChildId(listPosition: Int, expandedListPosition: Int): Long .
3. getChildView() Returns the view for the child at given position within a group at given position. Actual method is getChildView(listPosition: Int, expandedListPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup): View . In this method, define the ui for the child element. You can check how we have defined the ui for any child element in getChildView() method in CustomExpandableListAdapter class.
4. getChildrenCount() It returns the number of children in group at given position. Actual method is getChildrenCount(listPosition: Int): Int .
5. getGroup() Returns the data associated with group at given position (i.e. listPosition). Actual method is getGroup(listPosition: Int): Any .
6. getGroupCount() Returns the number of groups. Actual method is getGroupCount(): Int .
7. getGroupId() Returns the id of the group at given position (i.e. listPosition). Actual method is getGroupId(listPosition: Int): Long.
8. getGroupView() Return the view of group at given position (i.e. listPosition). Actual method is getGroupView(listPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View. In this method, we define the view for group. Notice that how we have used list_group.xml file for any group in CustomExpandableListAdapter class.
9. hasStableIds() It indicates whether group or child ids are stable across changes to the underlying data.
10. isChildSelectable() It indicates whether child at given position in given group is selectable or not. Actual method is isChildSelectable(listPosition: Int, expandedListPosition: Int): Boolean

Since adapter class is ready now. We will use ExpandableListView widget in xml file. Then, we will access this ExpandableListView using kotlin file and perform some operations on it.

6. Use ExpandableListView Widget in xml file

Open src/main/res/layout/activity_main.xml file and add below code into it.

<?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:orientation="vertical">

	<ExpandableListView
		android:id="@+id/expandableListView"
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:dividerHeight="0.5dp">

	</ExpandableListView>

</LinearLayout>

In activity_main.xml file, we have used ExpandableListView widget. This widget is responsible for providing hierarchy level view. Now, we will access this ExpandableListView using kotlin file and perform some actions on it.

7. Access ExpandableListView using Kotlin file

Open src/main/java/com.tutorialwing.expandablelistview/MainActivity.kt file and add below code into it.

package com.tutorialwing.expandablelistview

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.ExpandableListAdapter
import android.widget.ExpandableListView
import android.widget.Toast

import java.util.ArrayList
import java.util.HashMap

class MainActivity : AppCompatActivity() {

    internal var expandableListView: ExpandableListView? = null
    internal var adapter: ExpandableListAdapter? = null
    internal var titleList: List<String> ? = null

    val data: HashMap<String, List<String>>
        get() {
            val listData = HashMap<String, List<String>>()

            val redmiMobiles = ArrayList<String>()
            redmiMobiles.add("Redmi Y2")
            redmiMobiles.add("Redmi S2")
            redmiMobiles.add("Redmi Note 5 Pro")
            redmiMobiles.add("Redmi Note 5")
            redmiMobiles.add("Redmi 5 Plus")
            redmiMobiles.add("Redmi Y1")
            redmiMobiles.add("Redmi 3S Plus")

            val micromaxMobiles = ArrayList<String>()
            micromaxMobiles.add("Micromax Bharat Go")
            micromaxMobiles.add("Micromax Bharat 5 Pro")
            micromaxMobiles.add("Micromax Bharat 5")
            micromaxMobiles.add("Micromax Canvas 1")
            micromaxMobiles.add("Micromax Dual 5")

            val appleMobiles = ArrayList<String>()
            appleMobiles.add("iPhone 8")
            appleMobiles.add("iPhone 8 Plus")
            appleMobiles.add("iPhone X")
            appleMobiles.add("iPhone 7 Plus")
            appleMobiles.add("iPhone 7")
            appleMobiles.add("iPhone 6 Plus")

            val samsungMobiles = ArrayList<String>()
            samsungMobiles.add("Samsung Galaxy S9+")
            samsungMobiles.add("Samsung Galaxy Note 7")
            samsungMobiles.add("Samsung Galaxy Note 5 Dual")
            samsungMobiles.add("Samsung Galaxy S8")
            samsungMobiles.add("Samsung Galaxy A8")
            samsungMobiles.add("Samsung Galaxy Note 4")

            listData["Redmi"] = redmiMobiles
            listData["Micromax"] = micromaxMobiles
            listData["Apple"] = appleMobiles
            listData["Samsung"] = samsungMobiles

            return listData
        }

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

        expandableListView = findViewById(R.id.expandableListView)
        if (expandableListView != null) {
            val listData = data
            titleList = ArrayList(listData.keys)
            adapter = CustomExpandableListAdapter(this, titleList as ArrayList<String>, listData)
            expandableListView!!.setAdapter(adapter)

            expandableListView!!.setOnGroupExpandListener { groupPosition -> Toast.makeText(applicationContext, (titleList as ArrayList<String>)[groupPosition] + " List Expanded.", Toast.LENGTH_SHORT).show() }

            expandableListView!!.setOnGroupCollapseListener { groupPosition -> Toast.makeText(applicationContext, (titleList as ArrayList<String>)[groupPosition] + " List Collapsed.", Toast.LENGTH_SHORT).show() }

            expandableListView!!.setOnChildClickListener { parent, v, groupPosition, childPosition, id ->
                Toast.makeText(applicationContext, "Clicked: " + (titleList as ArrayList<String>)[groupPosition] + " -> " + listData[(titleList as ArrayList<String>)[groupPosition]]!!.get(childPosition), Toast.LENGTH_SHORT).show()
                false
            }
        }
    }
}

Here, we have accessed expandableListView using kotlin file i.e. In MainActivity.kt file. Then, an instance of CustomExpandableListAdapter class has been created. Then, this adapter class is set as an adapter of expandableListView.

After that we have set some listeners (GroupExpandListener, GroupCollapseListener and ChildClickListener) to expandableListView.




8. Setting Listeners in expandableListView

You can set different listeners in expandableListView –

  • (i) Group Expand Listener
  • (ii) Group Collapse Listener
  • (iii) Child Click Listener
8.1 Setting GroupExpandListener in ExpandableListView

We need group expand listener to perform the task whenever any group is expanded. You can set group expand listener in expandableListView using kotin as below –

expandableListView!!.setOnGroupExpandListener { 
   groupPosition -> Toast.makeText(applicationContext, (titleList as ArrayList<String>)[groupPosition] + " List Expanded.", Toast.LENGTH_SHORT).show() 
}

Here, we are showing a toast message whenever any group is expanded and this method is called.

You can also perform the same task by overriding onGroupExpanded(groupPosition: Int) method in adapter class of ExpandableListView. For example, in given CustomExpandableListAdapter.kt class, you can override onGroupExpanded(groupPosition: Int) method as below –

override fun onGroupExpanded(groupPosition: Int) {
   Toast.makeText(context, (titleList as ArrayList<String>)[groupPosition] + " List Expanded.", Toast.LENGTH_SHORT).show()
}

Here, we are also showing a toast message whenever this method is called.

8.2 Setting GroupCollapsedListener in ExpandableListView

We need groupCollapsed listener to perform some operations whenever any group is collapsed. You can set group collapsed listener in expandableListView using kotlin as shown below –

expandableListView!!.setOnGroupCollapseListener { groupPosition ->
     Toast.makeText(applicationContext, (titleList as ArrayList<String>)[groupPosition] + " List Collapsed.", Toast.LENGTH_SHORT).show()
}

Or, you can perform same task by overriding onGroupCollapsed(groupPosition: Int) method in adapter class of expandableListView. For example, in given CustomExpandableListAdapter.kt class, you can override onGroupCollapsed(groupPosition: Int) method as below –

override fun onGroupCollapsed(groupPosition: Int) {
   Toast.makeText(context, (titleList as ArrayList<String>)[groupPosition] + " List Collapsed.", Toast.LENGTH_SHORT).show()
}
8.3 Setting Child Click Listener in ExpandableListView

We need child click listener in expandableListView to perform some operations when any child item is clicked. You can set child click listener in expandableListView using kotlin as shown below –

expandableListView!!.setOnChildClickListener { 
    parent, v, groupPosition, childPosition, id -> 
    Toast.makeText(applicationContext, "Clicked: " + (titleList as ArrayList<String>)[groupPosition] + " -> " + listData[(titleList as ArrayList<String>)[groupPosition]]!!.get(childPosition), Toast.LENGTH_SHORT).show()
    false
}

Here, we are also showing toast message whenever any child item is clicked.

Since AndroidManifest.xml file is very important in any android application, we are also going to see the content inside this file.

AndroidManifest.xml file

Code inside main/AndroidManifest.xml file is as below.

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.tutorialwing.expandablelistview"
		  xmlns:android="http://schemas.android.com/apk/res/android">

	<application
		android:allowBackup="true"
		android:icon="@mipmap/ic_launcher"
		android:label="@string/app_name"
		android:roundIcon="@mipmap/ic_launcher_round"
		android:supportsRtl="true"
		android:theme="@style/AppTheme">
		<activity android:name=".MainActivity">
			<intent-filter>
				<action android:name="android.intent.action.MAIN"/>

				<category android:name="android.intent.category.LAUNCHER"/>
			</intent-filter>
		</activity>
	</application>

</manifest>

When we run the program, we will get output as shown above.

That’s end of our tutorial on Android ExpandableListView using Kotlin.

Support Us

If you like Tutorialwing and would like to contribute, you can email an article on any educational topic at tutorialwing@gmail.com. We would love to publish your article. See your article on Tutorialwing and help others with your knowledge. Follow Facebook, LinkedIn, Google+, Twitter, Youtube for latest updates.
Greetings!
We have recently published 100+ articles on android tutorials with kotlin and java. If you need, you may visit Android Tutorial for beginners page. You can also check Kotlin Tutorial for beginners