Using ExpandableListView in Android with Kotlin

Using ExpandableListView in Android with Kotlin


Last updated on

Overview of ExpandableListView

ExpandableListView is an Android widget that provides a way to group list data into categories, each of which can be expanded to show or collapsed to hide its children. This is particularly useful for displaying complex lists with multiple levels of data.

Setting Up the Project

To get started, you need to set up an Android project in Android Studio. Follow these steps:

  1. Open Android Studio and create a new project.
  2. Select “Empty Activity” and click “Next”.
  3. Name your project and set the language to “Kotlin”.
  4. Click “Finish” to create the project.

Creating the Layout

Next, you’l.l need to create the layout for your ExpandableListView. Open the activity_main.xml file and add the following XML code:


<RelativeLayout 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">

    <ExpandableListView
        android:id="@+id/expandable_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

This layout simply includes an ExpandableListView that takes up the entire screen.

Setting Up the Data

To populate the ExpandableListView, you need to define the data. Typically, this data is structured in the form of a HashMap where each key represents a group and each value is a list of children for that group.

Create a new file called DataProvider.kt and add the following code:

object DataProvider {
    fun getData(): HashMap<String, List<String>> {
        val expandableListDetail = HashMap<String, List<String>>()

        val group1 = listOf("Child 1", "Child 2")
        val group2 = listOf("Child 3", "Child 4")

        expandableListDetail["Group 1"] = group1
        expandableListDetail["Group 2"] = group2

        return expandableListDetail
    }
}

Creating the Adapter

Next, create a custom adapter to bridge the data and the ExpandableListView. Create a new file called CustomExpandableListAdapter.kt and add the following code:

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

class CustomExpandableListAdapter(
    private val context: Context,
    private val expandableListTitle: List<String>,
    private val expandableListDetail: HashMap<String, List<String>>
) : BaseExpandableListAdapter() {

    override fun getChild(listPosition: Int, expandedListPosition: Int): Any {
        return this.expandableListDetail[this.expandableListTitle[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(android.R.layout.simple_list_item_1, null)
        }
        val expandedListTextView = convertView!!.findViewById<TextView>(android.R.id.text1)
        expandedListTextView.text = expandedListText
        return convertView
    }

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

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

    override fun getGroupCount(): Int {
        return this.expandableListTitle.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(android.R.layout.simple_expandable_list_item_1, null)
        }
        val listTitleTextView = convertView!!.findViewById<TextView>(android.R.id.text1)
        listTitleTextView.text = listTitle
        return convertView
    }

    override fun hasStableIds(): Boolean {
        return false
    }

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

Implementing ExpandableListView

Now, let’s put everything together in the MainActivity. Open MainActivity.kt and add the following code:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var expandableListAdapter: CustomExpandableListAdapter
    private lateinit var expandableListTitle: List<String>
    private lateinit var expandableListDetail: HashMap<String, List<String>>

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

        expandableListDetail = DataProvider.getData()
        expandableListTitle = ArrayList(expandableListDetail.keys)
        expandableListAdapter = CustomExpandableListAdapter(this, expandableListTitle, expandableListDetail)
        expandableListView.setAdapter(expandableListAdapter)
    }
}

This code initializes the ExpandableListView, sets the adapter, and populates it with data.

Handling Click Events

To handle click events on group and child items, add the following code to MainActivity:

expandableListView.setOnGroupExpandListener { groupPosition ->
    // Handle group expand event
}

expandableListView.setOnGroupCollapseListener { groupPosition ->
    // Handle group collapse event
}

expandableListView.setOnChildClickListener { parent, v, groupPosition, childPosition, id ->
    // Handle child click event
    false
}

Conclusion

ExpandableListView is a powerful widget in Android that allows you to display data in a hierarchical format. By following this guide, you should be able to implement an ExpandableListView in your Android application, customize it with your own data, and handle various events to create a dynamic user experience.

© 2024 Norbel Ambanumben