Kotlin ExpandableListView With CheckBox Android | Multiple checkboxes

kotlin sqlite multiple tables, kotlin recyclerview checkbox, kotlin recyclerview button, kotlin load html javascript, kotlin recyclerview searchview, kotlin recyclerview search using edittext, kotlin listview with edittext, kotlin recyclerview with edittext, kotlin swipe to delete listview, kotlin recyclerview swipe to delete, kotlin expandablelistview with checkbox, kotlin custom ratingbar, kotlin change tab, Kotlin Select Multiple Images From Gallery, Kotlin Custom Dialog With Image And Title, kotlin select multiple video

Learn about Kotlin ExpandableListView With CheckBox Android Example.

I will explain you how to create expandable listview with multiple checkboxes in android using kotlin.

Checkbox will be present in all the parent as well as child rows. We will handle all these checkbox selection.

After selecting some checkbox, we will pass them to the next activity so that we can see how to do next tasks with the selected checkboxes.

We will solve the general problems like

  1. checkbox gets unchecked while scrolling the listview
  2. Different positioned or multiple checkboxes are checked when click on single box

First of all, see the following output video.

 

Step 1. A new Kotlin Project

Make a new project in android studio with kotlin as the primary source language.

Also, keep in mind to make empty activity as the default activity.

Step 2. Changing Colors

In your app->res->values directory, there is a file named colors.xml 

Update this  colors.xml  as per the following code

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="colorWhite">#fff</color>
    <color name="colorBlack">#000</color>
</resources>

Step 3. Download Images

Click the following link to download some necessary images.

https://demonuts.com/wp-content/uploads/2018/05/ExpandableCheckImages.zip

It contains three images,

  1. icon_checked,
  2. icon_unchecked and
  3. icon_dot

Now, put all the above images into the app->res->drawable directory.

Step 4. Some XML in Drawable

Go to app->res->drawable directory. Inside drawable folder, make a new xml file and give it a name like

background_bordered_theme.xml

You need to add the following in background_bordered_theme.xml

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

    <corners
        android:radius="5dp" />

    <stroke
        android:width="1dp" />

    <solid
        android:color="@android:color/transparent" />
</shape>

Now create another layout xml file and give it a name custom_checkbox_theme.xml

Copy below code into it

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_checked="true"
        android:drawable="@drawable/icon_checked" />
    <item android:state_pressed="true"
        android:drawable="@drawable/icon_checked" />
    <item android:state_pressed="false"
        android:drawable="@drawable/icon_unchecked" />
</selector>

Make third xml file named edit_text_theme.xml and copy the following in it

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview_background_shape">
    <stroke
        android:width="0dp"
        android:color="@android:color/white" />
    <padding
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp" />
    <corners android:radius="2dp" />
    <solid android:color="@color/colorWhite"
        android:alpha="0.3"/>
</shape>

Step 5. Layout Files For ListView Row

Navigate to app->res->layout directory and make new XML file named child_list_layout_choose_category.xml 

Below is the coding lines for child_list_layout_choose_category.xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/edit_text_theme">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center|right">

            <ImageView
                android:layout_width="15dp"
                android:layout_height="15dp"
                android:visibility="visible"
                android:background="@drawable/icon_dot"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <TextView
                android:id="@+id/tvSubCategoryName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="50dp"
                android:layout_marginLeft="15dp"
                android:gravity="center_vertical|left"
                android:textColor="@color/colorBlack"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center">

            <CheckBox
                android:id="@+id/cbSubCategory"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:focusable="false"
                android:button="@drawable/custom_checkbox_theme" />

        </LinearLayout>
    </LinearLayout>

    <View
        android:id="@+id/viewDivider"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/colorBlack"/>
</LinearLayout>

Now in the same directory, make another file called group_list_layout_choose_categories.xml with the following source code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants">

    <View
        android:layout_width="match_parent"
        android:layout_height="10dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/edit_text_theme">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center">

            <ImageView
                android:id="@+id/ivCategory"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:visibility="gone"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <TextView
                android:id="@+id/tvMainCategoryName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="50dp"
                android:gravity="center_vertical|left"
                android:textColor="@color/colorBlack"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center">

            <CheckBox
                android:id="@+id/cbMainCategory"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:focusable="false"
                android:button="@drawable/custom_checkbox_theme" />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Another file will be group_list_layout_my_categories.xml and with below lines

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants">

    <View
        android:layout_width="match_parent"
        android:layout_height="10dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/background_bordered_theme">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center">

            <ImageView
                android:id="@+id/ivCategory"
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:visibility="gone"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1">

            <TextView
                android:id="@+id/tvMainCategoryName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="50dp"
                android:gravity="center_vertical|left"
                android:textColor="@color/colorBlack"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.3"
            android:gravity="center">

            <CheckBox
                android:id="@+id/cbMainCategory"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:focusable="false"
                android:button="@drawable/custom_checkbox_theme" />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Step 6. Model Directory

Create a new folder called Model in app->java->your package name (It is the same path where your MainActivity is present)

Below image shows the directory structure where you need to create Model folder and two Kotlin files inside this Model folder.

android expandablelistview checkbox

 

Now make a new File named DataItem.kt and add the following

class DataItem {

    var categoryId: String? = null
    var categoryName: String? = null
    var isChecked = "NO"
    var subCategory: List<SubCategoryItem>? = null

    fun getCategoryIds(): String {
        return categoryId.toString()
    }

    fun setCategoryIds(categoryId: String) {
        this.categoryId = categoryId
    }

    fun getCategoryNames(): String {
        return categoryName.toString()
    }

    fun setCategoryNames(categoryName: String) {
        this.categoryName = categoryName
    }

    fun getIsChecked(): String {
        return isChecked
    }

    fun setIsChecked(isChecked: String) {
        this.isChecked = isChecked
    }

    fun getSubCategorys(): List<SubCategoryItem> {
        return this!!.subCategory!!
    }

    fun setSubCategorys(subCategory: List<SubCategoryItem>) {
        this.subCategory = subCategory
    }

}

This class is representing the getter and setter methods for the parent rows of expandable list view.

Now make another class with the name SubCategoryItem.kt and add the below in it

class SubCategoryItem {

    var categoryId: String? = null
    var subId: String? = null
    var subCategoryName: String? = null
    var isChecked: String? = null

    fun getCategoryIds(): String {
        return categoryId.toString()
    }

    fun setCategoryIds(categoryId: String) {
        this.categoryId = categoryId
    }

    fun getSubIds(): String {
        return subId.toString()
    }

    fun setSubIds(subId: String) {
        this.subId = subId
    }

    fun getSubCategoryNames(): String {
        return subCategoryName.toString()
    }

    fun setSubCategoryNames(subCategoryName: String) {
        this.subCategoryName = subCategoryName
    }

    fun getIsChecked(): String {
        return isChecked.toString()
    }

    fun setIsChecked(isChecked: String) {
        this.isChecked = isChecked
    }

}

Above file is for maintaining the data of the sub category or children of the expandable list view.

Step 7. Two More Classes

Create a new Kotlin file as per shown in the image in the step 6.

Name of this file should be ConstantManager.kt and following is it’s source lines

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

internal class ConstantManager {


    object Parameter {
        val IS_CHECKED = "is_checked"
        val SUB_CATEGORY_NAME = "sub_category_name"
        val CATEGORY_NAME = "category_name"
        val CATEGORY_ID = "category_id"
        val SUB_ID = "sub_id"
    }

    companion object {

        val CHECK_BOX_CHECKED_TRUE = "YES"
        val CHECK_BOX_CHECKED_FALSE = "NO"

        var childItems = ArrayList<ArrayList<HashMap<String, String>>>()
        var parentItems = ArrayList<HashMap<String, String>>()
    }
}

This file contains some constant variables so that we can use them in the entire project.

Now make new Kotlin file as MyCategoriesExpandableListAdapter.kt and write below in it

import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseExpandableListAdapter
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import java.util.ArrayList
import java.util.HashMap

/**
 * Created by zerones on 04-Oct-17.
 */

class MyCategoriesExpandableListAdapter(
    private val activity: Activity, parentItems: ArrayList<HashMap<String, String>>,
    childItems: ArrayList<ArrayList<HashMap<String, String>>>, private val isFromMyCategoriesFragment: Boolean
) : BaseExpandableListAdapter() {
    //    private final ArrayList<HashMap<String, String>> childItems;
    private val inflater: LayoutInflater
    private var child: HashMap<String, String>? = null
    private var count = 0

    init {

        parentItemss = parentItems
        childItemss = childItems
        inflater = activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

    }

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

    override fun getChildrenCount(groupPosition: Int): Int {
        return childItemss[groupPosition].size
    }

    override fun getGroup(i: Int): Any? {
        return null
    }

    override fun getChild(i: Int, i1: Int): Any? {
        return null
    }

    override fun getGroupId(i: Int): Long {
        return 0
    }

    override fun getChildId(i: Int, i1: Int): Long {
        return 0
    }

    override fun hasStableIds(): Boolean {
        return false
    }

    override fun getGroupView(groupPosition: Int, b: Boolean, convertView: View?, viewGroup: ViewGroup): View {
        var convertView = convertView
        val viewHolderParent: ViewHolderParent
        if (convertView == null) {

            if (isFromMyCategoriesFragment) {
                convertView = inflater.inflate(R.layout.group_list_layout_my_categories, null)
            } else {
                convertView = inflater.inflate(R.layout.group_list_layout_choose_categories, null)
            }
            viewHolderParent = ViewHolderParent()

            viewHolderParent.tvMainCategoryName = convertView!!.findViewById(R.id.tvMainCategoryName)
            viewHolderParent.cbMainCategory = convertView.findViewById(R.id.cbMainCategory)
            viewHolderParent.ivCategory = convertView.findViewById(R.id.ivCategory)
            convertView.tag = viewHolderParent
        } else {
            viewHolderParent = convertView.tag as ViewHolderParent
        }

        if (parentItemss[groupPosition][ConstantManager.Parameter.IS_CHECKED]!!.equals(
                ConstantManager.CHECK_BOX_CHECKED_TRUE,
                ignoreCase = true
            )
        ) {
            viewHolderParent.cbMainCategory!!.isChecked = true
            notifyDataSetChanged()

        } else {
            viewHolderParent.cbMainCategory!!.isChecked = false
            notifyDataSetChanged()
        }

        viewHolderParent.cbMainCategory!!.setOnClickListener {
            if (viewHolderParent.cbMainCategory!!.isChecked) {
                parentItemss[groupPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_TRUE

                for (i in 0 until childItemss[groupPosition].size) {
                    childItemss[groupPosition][i][ConstantManager.Parameter.IS_CHECKED] =
                        ConstantManager.CHECK_BOX_CHECKED_TRUE
                }
                notifyDataSetChanged()

            } else {
                parentItemss[groupPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_FALSE
                for (i in 0 until childItemss[groupPosition].size) {
                    childItemss[groupPosition][i][ConstantManager.Parameter.IS_CHECKED] =
                        ConstantManager.CHECK_BOX_CHECKED_FALSE
                }
                notifyDataSetChanged()
            }
        }

        ConstantManager.childItems = childItemss
        ConstantManager.parentItems = parentItemss

        viewHolderParent.tvMainCategoryName!!.text = parentItemss[groupPosition][ConstantManager.Parameter.CATEGORY_NAME]

        return convertView
    }

    override fun getChildView(
        groupPosition: Int,
        childPosition: Int,
        b: Boolean,
        convertView: View?,
        viewGroup: ViewGroup
    ): View {
        var convertView = convertView

        val viewHolderChild: ViewHolderChild
        child = childItemss[groupPosition][childPosition]

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.child_list_layout_choose_category, null)
            viewHolderChild = ViewHolderChild()

            viewHolderChild.tvSubCategoryName = convertView!!.findViewById(R.id.tvSubCategoryName)
            viewHolderChild.cbSubCategory = convertView.findViewById(R.id.cbSubCategory)
            viewHolderChild.viewDivider = convertView.findViewById(R.id.viewDivider)
            convertView.tag = viewHolderChild
        } else {
            viewHolderChild = convertView.tag as ViewHolderChild
        }

        if (childItemss[groupPosition][childPosition][ConstantManager.Parameter.IS_CHECKED]!!.equals(
                ConstantManager.CHECK_BOX_CHECKED_TRUE,
                ignoreCase = true
            )
        ) {
            viewHolderChild.cbSubCategory!!.isChecked = true
            notifyDataSetChanged()
        } else {
            viewHolderChild.cbSubCategory!!.isChecked = false
            notifyDataSetChanged()
        }

        viewHolderChild.tvSubCategoryName!!.text = child!![ConstantManager.Parameter.SUB_CATEGORY_NAME]
        viewHolderChild.cbSubCategory!!.setOnClickListener {
            if (viewHolderChild.cbSubCategory!!.isChecked) {
                count = 0
                childItemss[groupPosition][childPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_TRUE
                notifyDataSetChanged()
            } else {
                count = 0
                childItemss[groupPosition][childPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_FALSE
                notifyDataSetChanged()
            }

            for (i in 0 until childItemss[groupPosition].size) {
                if (childItemss[groupPosition][i][ConstantManager.Parameter.IS_CHECKED]!!.equals(
                        ConstantManager.CHECK_BOX_CHECKED_TRUE,
                        ignoreCase = true
                    )
                ) {
                    count++
                }
            }
            if (count == childItemss[groupPosition].size) {
                parentItemss[groupPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_TRUE
                notifyDataSetChanged()
            } else {
                parentItemss[groupPosition][ConstantManager.Parameter.IS_CHECKED] =
                    ConstantManager.CHECK_BOX_CHECKED_FALSE
                notifyDataSetChanged()
            }


            ConstantManager.childItems = childItemss
            ConstantManager.parentItems = parentItemss
        }

        return convertView
    }

    override fun isChildSelectable(i: Int, i1: Int): Boolean {
        return false
    }

    override fun onGroupCollapsed(groupPosition: Int) {
        super.onGroupCollapsed(groupPosition)
    }

    override fun onGroupExpanded(groupPosition: Int) {
        super.onGroupExpanded(groupPosition)
    }

    private inner class ViewHolderParent {

        internal var tvMainCategoryName: TextView? = null
        internal var cbMainCategory: CheckBox? = null
        internal var ivCategory: ImageView? = null
    }

    private inner class ViewHolderChild {

        internal var tvSubCategoryName: TextView? = null
        internal var cbSubCategory: CheckBox? = null
        internal var viewDivider: View? = null
    }

    companion object {

        lateinit var childItemss: ArrayList<ArrayList<HashMap<String, String>>>
        lateinit var parentItemss: ArrayList<HashMap<String, String>>
    }


}

Above is the adapter which will create our expandable listview.

Here, getGroupView() method will create the rows of parent list view.

getChildView() method is responsible for the look and feel of the child rows of expandable list view.

Step 8. Main Files To Write

Code for activity_main.xml file is as the below

<?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"
              android:orientation="vertical"
              tools:context=".MainActivity">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="10dp"
            android:text="Send Data To Next Activity"/>

    <ExpandableListView
            android:id="@+id/lvCategory"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:childDivider="@color/colorBlack"
            android:divider="@null"
            android:dividerHeight="0dp" />


</LinearLayout>

One button and one expandable list view is there in the above file. When the user clicks the button, compiler will open the Next activity that we will create very soon.

Now in your MainActivity.kt file, add the following

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ExpandableListView
import com.example.listviewexpandablecheckboxkotlin.Model.DataItem
import com.example.listviewexpandablecheckboxkotlin.Model.SubCategoryItem
import java.util.ArrayList
import java.util.HashMap

class MainActivity : AppCompatActivity() {

    private var btn: Button? = null
    private var lvCategory: ExpandableListView? = null

    private var arCategory: ArrayList<DataItem>? = null
    private var arSubCategory: ArrayList<SubCategoryItem>? = null
    private val arSubCategoryFinal: ArrayList<ArrayList<SubCategoryItem>>? = null

    private var parentItems: ArrayList<HashMap<String, String>>? = null
    private var childItems: ArrayList<ArrayList<HashMap<String, String>>>? = null
    private var myCategoriesExpandableListAdapter: MyCategoriesExpandableListAdapter? = null

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

        btn = findViewById(R.id.btn)

        btn!!.setOnClickListener {
            val intent = Intent(this@MainActivity, CheckedActivity::class.java)
            startActivity(intent)
        }

        setupReferences()
    }

    private fun setupReferences() {

        lvCategory = findViewById(R.id.lvCategory)
        arCategory = ArrayList<DataItem>()
        arSubCategory = ArrayList<SubCategoryItem>()
        parentItems = ArrayList()
        childItems = ArrayList()

        var dataItem = DataItem()
        dataItem.setCategoryIds("1")
        dataItem.setCategoryNames("Adventure")

        arSubCategory = ArrayList<SubCategoryItem>()
        for (i in 1..5) {

            val subCategoryItem = SubCategoryItem()
            subCategoryItem.setCategoryIds(i.toString())
            subCategoryItem.setIsChecked(ConstantManager.CHECK_BOX_CHECKED_FALSE)
            subCategoryItem.setSubCategoryNames("Adventure: $i")
            arSubCategory!!.add(subCategoryItem)
        }
        dataItem.setSubCategorys(arSubCategory!!)
        arCategory!!.add(dataItem)

        dataItem = DataItem()
        dataItem.setCategoryIds("2")
        dataItem.setCategoryNames("Art")
        arSubCategory = ArrayList<SubCategoryItem>()
        for (j in 1..5) {

            val subCategoryItem = SubCategoryItem()
            subCategoryItem.setCategoryIds(j.toString())
            subCategoryItem.setIsChecked(ConstantManager.CHECK_BOX_CHECKED_FALSE)
            subCategoryItem.setSubCategoryNames("Art: $j")
            arSubCategory!!.add(subCategoryItem)
        }
        dataItem.setSubCategorys(arSubCategory!!)
        arCategory!!.add(dataItem)

        dataItem = DataItem()
        dataItem.setCategoryIds("3")
        dataItem.setCategoryNames("Cooking")
        arSubCategory = ArrayList<SubCategoryItem>()
        for (k in 1..5) {

            val subCategoryItem = SubCategoryItem()
            subCategoryItem.setCategoryIds(k.toString())
            subCategoryItem.setIsChecked(ConstantManager.CHECK_BOX_CHECKED_FALSE)
            subCategoryItem.setSubCategoryNames("Cooking: $k")
            arSubCategory!!.add(subCategoryItem)
        }

        dataItem.setSubCategorys(arSubCategory!!)
        arCategory!!.add(dataItem)

        Log.d("TAG", "setupReferences: " + arCategory!!.size)

        for (data in arCategory!!) {
            //                        Log.i("Item id",item.id);
            val childArrayList = ArrayList<HashMap<String, String>>()
            val mapParent = HashMap<String, String>()

            mapParent[ConstantManager.Parameter.CATEGORY_ID] = data.getCategoryIds()
            mapParent[ConstantManager.Parameter.CATEGORY_NAME] = data.getCategoryNames()

            var countIsChecked = 0
            for (subCategoryItem in data.getSubCategorys()) {

                val mapChild = HashMap<String, String>()
                mapChild[ConstantManager.Parameter.SUB_ID] = subCategoryItem.getSubIds()
                mapChild[ConstantManager.Parameter.SUB_CATEGORY_NAME] = subCategoryItem.getSubCategoryNames()
                mapChild[ConstantManager.Parameter.CATEGORY_ID] = subCategoryItem.getCategoryIds()
                mapChild[ConstantManager.Parameter.IS_CHECKED] = subCategoryItem.getIsChecked()

                if (subCategoryItem.getIsChecked().equals(ConstantManager.CHECK_BOX_CHECKED_TRUE, ignoreCase = true)) {

                    countIsChecked++
                }
                childArrayList.add(mapChild)
            }

            if (countIsChecked == data.getSubCategorys().size) {

                data.setIsChecked(ConstantManager.CHECK_BOX_CHECKED_TRUE)
            } else {
                data.setIsChecked(ConstantManager.CHECK_BOX_CHECKED_FALSE)
            }

            mapParent[ConstantManager.Parameter.IS_CHECKED] = data.getIsChecked()
            childItems!!.add(childArrayList)
            parentItems!!.add(mapParent)

        }

        ConstantManager.parentItems = parentItems as ArrayList<HashMap<String, String>>
        ConstantManager.childItems = childItems as ArrayList<ArrayList<HashMap<String, String>>>

        myCategoriesExpandableListAdapter = MyCategoriesExpandableListAdapter(this, parentItems!!, childItems!!, false)
        lvCategory!!.setAdapter(myCategoriesExpandableListAdapter)
    }
}

Step 8. Making Checked Activity

Create a new activity and give it a name like Checked Activity.

Below is the source snippet for activity_checked.xml

<?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:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:paddingLeft="10dp"
              android:paddingTop="20dp"
              tools:context=".CheckedActivity">

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="Selected Parents : "/>

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="20sp"
            android:id="@+id/parent"/>

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="Selected Children : "/>

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="20sp"
            android:id="@+id/child"/>

</LinearLayout>

Now write down the below coding lines in CheckedActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class CheckedActivity : AppCompatActivity() {

    private var tvParent: TextView? = null
    private var tvChild: TextView? = null

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

        tvParent = findViewById(R.id.parent)
        tvChild = findViewById(R.id.child)

        for (i in 0 until MyCategoriesExpandableListAdapter.parentItemss.size) {

            val isChecked =
                MyCategoriesExpandableListAdapter.parentItemss.get(i).get(ConstantManager.Parameter.IS_CHECKED)

            if (isChecked.equals(ConstantManager.CHECK_BOX_CHECKED_TRUE, ignoreCase = true)) {

                val a = tvParent!!.text
                val b = MyCategoriesExpandableListAdapter.parentItemss.get(i).get(
                    ConstantManager.Parameter.CATEGORY_NAME)
                val c = "$a  $b"

                tvParent!!.setText( c )

            }

            for (j in 0 until MyCategoriesExpandableListAdapter.childItemss.get(i).size) {

                val isChildChecked =
                    MyCategoriesExpandableListAdapter.childItemss.get(i).get(j).get(ConstantManager.Parameter.IS_CHECKED)

                if (isChildChecked.equals(ConstantManager.CHECK_BOX_CHECKED_TRUE, ignoreCase = true)) {
                    tvChild!!.text =
                        tvChild!!.text.toString() + " , " + MyCategoriesExpandableListAdapter.parentItemss.get(i).get(
                            ConstantManager.Parameter.CATEGORY_NAME
                        ) + " " + (j + 1)
                }

            }

        }
    }
}

In this activity, compiler will print the selected parents and child row checkbox names.

Download Kotlin ExpandableListView With CheckBox Android

https://github.com/demonuts/Kotlin-ExpandableListView-With-CheckBox-Android-Multiple-checkboxes