In this article, we will learn about android ExpandableListView using Kotlin. We will go through various example that demonstrates how to use different attributes of ExpandableListView. 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.
In this article, we will get answer to questions like –
- What is ExpandableListView?
- Why should we consider ExpandableListView while designing ui for any app?
- What are possibilities using ExpandableListView while designing ui? etc.
Let’s have a quick demo of things we want to cover in this tutorial –
Output
Getting Started
We can define android ExpandableListView widget 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 – We 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 we have used ExpandableListView inside ScrollView, we can not use wrap_content for android:layout_height because ScrollView can have any height.
Now, how do we use ExpandableListView in android application ?
Creating New Project
At first, we will create an application.
So, follow steps below to create any android project in Kotlin –
Step | Description |
---|---|
1. | Open Android Studio (Ignore if already done). |
2. | Go to File => New => New Project. This will open a new window. Then, under Phone and Tablet section, select Empty Activity. Then, click Next. |
3. | In next screen, select project name as ExpandableListView. Then, fill other required details. |
4. | Then, clicking on Finish button creates new project. |
Newbie in Android ?
Some very important concepts (Recommended to learn before you move ahead)
Before we move ahead, we need to setup for viewBinding to access Android ExpandableListView Using Kotlin file without using findViewById() method.
Setup ViewBinding
Add viewBinding true in app/build.gradle file.
android { // OTHER CODE... buildFeatures { viewBinding true } }
Now, set content in activity using view binding.
Open MainActivity.kt file and write below code in it.
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) val view = binding.root setContentView(view) } }
Now, we can access view in Kotlin file without using findViewById() method.
Using ExpandableListView in Kotlin
Follow steps below to use ExpandableListView in newly created project –
- Open res/values/strings.xml file. Then, add below code into it.
<resources> <string name="app_name">ExpandableListView</string> </resources>
-
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.
-
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.
-
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.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseExpandableListAdapter import android.widget.TextView import com.tutorialwing.expandablelistview.databinding.ListGroupBinding import com.tutorialwing.expandablelistview.databinding.ListItemBinding class CustomExpandableListAdapter internal constructor( private val context: Context, private val titleList: List<String>, private val dataList: HashMap<String, List<String>> ) : BaseExpandableListAdapter() { private val inflater: LayoutInflater = LayoutInflater.from(context) private lateinit var groupBinding: ListGroupBinding private lateinit var itemBinding: ListItemBinding 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, view: View?, parent: ViewGroup ): View { var convertView = view val holder: ItemViewHolder if (convertView == null) { itemBinding = ListItemBinding.inflate(inflater) convertView = itemBinding.root holder = ItemViewHolder() holder.label = itemBinding.expandedListItem convertView.tag = holder } else { holder = convertView.tag as ItemViewHolder } val expandedListText = getChild(listPosition, expandedListPosition) as String holder.label!!.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, view: View?, parent: ViewGroup ): View { var convertView = view val holder: GroupViewHolder if (convertView == null) { groupBinding = ListGroupBinding.inflate(inflater) convertView = groupBinding.root holder = GroupViewHolder() holder.label = groupBinding.listTitle convertView.tag = holder } else { holder = convertView.tag as GroupViewHolder } val listTitle = getGroup(listPosition) as String holder.label!!.text = listTitle return convertView } override fun hasStableIds(): Boolean { return false } override fun isChildSelectable(listPosition: Int, expandedListPosition: Int): Boolean { return true } inner class ItemViewHolder { internal var label: TextView? = null } inner class GroupViewHolder { internal var label: TextView? = null } }
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.
- Open res/layout/activity_main.xml file. Then, add below code in it –
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/expandableListView" android:layout_width="match_parent" android:layout_height="match_parent" android:dividerHeight="0.5dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
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.
-
We can also access it in Kotlin File, MainActivity.kt, as below –
package com.tutorialwing.expandablelistview import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.ExpandableListAdapter import android.widget.ExpandableListView import android.widget.Toast import com.tutorialwing.expandablelistview.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private var adapter: ExpandableListAdapter? = null private 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) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) setupExpandableListView() } private fun setupExpandableListView() { val expandableListView = binding.expandableListView 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.
Now, run the application. We will get output as below –
8. Setting Listeners in expandableListView
You can set different listeners in expandableListView –
-
Setting GroupExpandListener in ExpandableListView
We need group expand listener to perform the task whenever any group is expanded. We 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.
We can also perform the same task by overriding onGroupExpanded(groupPosition: Int) method in adapter class of ExpandableListView. For example, in given CustomExpandableListAdapter.kt class, we 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.
-
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() }
-
Setting Child Click Listener in ExpandableListView
We need child click listener in expandableListView to perform some operations when any child item is clicked. We 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.
Different Attributes of ExpandableListView in XML
Now, we will see how to use different attributes of Android ExpandableListView using Kotlin to customise it –
Set Id of ExpandableListView
Many a time, we need id of View to access it in kotlin file or create ui relative to that view in xml file. So, we can set id of ExpandableListView using android:id attribute like below –
<ExpandableListView android:id="@+id/expandableListView_ID" />
Here, we have set id of ExpandableListView as expandableListView_ID using android:id=”” attribute. So, if we need to reference this ExpandableListView, we need to use this id – expandableListView_ID.
Learn to Set ID of ExpandableListView Dynamically
Set Width of ExpandableListView
We use android:layout_width=”” attribute to set width of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" />
Width can be either “MATCH_PARENT” or “WRAP_CONTENT” or any fixed value (like 20dp, 30dp etc.).
Learn to Set Width of ExpandableListView Dynamically
Set Height of ExpandableListView
We use android:layout_height=”” attribute to set height of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Height can be either “MATCH_PARENT” or “WRAP_CONTENT” or any fixed value.
Learn to Set Height of ExpandableListView Dynamically
Set Padding of ExpandableListView
We use android:padding=”” attribute to set padding of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" />
Here, we have set padding of 10dp in ExpandableListView using android:padding=”” attribute.
Learn to Set Padding of ExpandableListView Dynamically
Set Margin of ExpandableListView
We use android:layout_margin=”” attribute to set margin of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" />
Here, we have set margin of 10dp in ExpandableListView using android:layout_margin=”” attribute.
Learn to Set Margin of ExpandableListView Dynamically
Set Background of ExpandableListView
We use android:background=”” attribute to set background of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#ff0000" />
Here, we have set background of color #ff0000 in ExpandableListView using android:background=”” attribute.
Learn to Set Background of ExpandableListView Dynamically
Set Visibility of ExpandableListView
We use android:visibility=”” attribute to set visibility of ExpandableListView.
We can do it as below –
<ExpandableListView android:id="@+id/expandableListView_ID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" />
Here, we have set visibility of ExpandableListView using android:visiblity=”” attribute. Visibility can be of three types – gone, visible and invisible
Learn to Set Visibility of ExpandableListView Dynamically
Thus, we have seen what is ExpandableListView, how can we use android ExpandableListView using Kotlin ? etc. We also went through different attributes of android ExpandableListView.
You must be logged in to post a comment.