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