Android ExpandableListView Example Tutorial

Filed Under: Android

Welcome to Android ExpandableListView Example Tutorial. In this tutorial we’ll implement an ExpandableListView which is used to group list data by categories. It’s sort of menu and submenus in a Android ListView.

Android ExpandableListView

Android ExpandableListView is a view that shows items in a vertically scrolling two-level list. It differs from a ListView by allowing two levels which are groups that can be easily expanded and collapsed by touching to view and their respective children items.
ExpandableListViewAdapter in android loads the data into the items associated with this view.

Following are some important methods that are used by this class :

  • setChildIndicator(Drawable) : This is used to show an indicator besides each item representing the current state. If the child is the last child for a group, the state state_last will be set
  • setGroupIndicator(Drawable) : An indicator is drawn besides the group representing its state i.e. expanded or collapsed. If the group is empty, the state state_empty will be set. If the group is expanded, the state state_expanded will be set
  • getGroupView() : It returns view for the list group header
  • getChildView() : It returns view for list child item

The notable interfaces that are implemented by this class are given below :

  • ExpandableListView.OnChildClickListener : This is overridden to implement the callback method that’s invoked when a child in the expanded list is clicked
  • ExpandableListView.OnGroupClickListener : This is overridden to implement the callback method that’s invoked when a group header in the expanded list is clicked
  • ExpandableListView.OnGroupCollapseListener : It is used for notifying when a group is collapsed
  • ExpandableListView.OnGroupExpandListener : It is used to notify when a group is expanded

Android ExpandableListView Project Structure

Android ExpandableListView, Android ExpandableListView example, ExpandableListView in android

This project consists of three classes.

  • A MainActivity that shows the layout with the ExpandableListView
  • An ExpandableListDataPump which represents a random data in a List and maps the child item data to the respective group headers using a HashMap
  • A CustomExpandableListAdapter which provides the MainActivity with the data from the ExpandableListDataPump class/li>

Android ExpandableListView Code

The activity_main.xml layout consists of an ExpandableListView in a RelativeLayout as shown below :


<RelativeLayout xmlns:android=""

        android:dividerHeight="0.5dp" />


The android:indicatorLeft is the left bound for an items indicator.

Note : We cannot use the value wrap_content for the android:layout_height attribute of the ExpandableListView in XML unless the parent’s size is strictly specified

The layout of the group header of each individual list is given below :


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=""
    android:orientation="vertical" android:layout_width="match_parent"
        android:paddingBottom="10dp" />

The layout row of the child items is given below :


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=""
    android:orientation="vertical" android:layout_width="match_parent"
        android:paddingBottom="10dp" />

The ExpandableListDataPump class is defined as below:

package com.journaldev.expandablelistview;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class ExpandableListDataPump {
    public static HashMap<String, List<String>> getData() {
        HashMap<String, List<String>> expandableListDetail = new HashMap<String, List<String>>();

        List<String> cricket = new ArrayList<String>();
        cricket.add("South Africa");

        List<String> football = new ArrayList<String>();

        List<String> basketball = new ArrayList<String>();
        basketball.add("United States");

        expandableListDetail.put("CRICKET TEAMS", cricket);
        expandableListDetail.put("FOOTBALL TEAMS", football);
        expandableListDetail.put("BASKETBALL TEAMS", basketball);
        return expandableListDetail;

In the above code the expandableListDetail object is used to map the group header strings to their respective children using an ArrayList of Strings.

package com.journaldev.expandablelistview;

import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

public class CustomExpandableListAdapter extends BaseExpandableListAdapter {

    private Context context;
    private List<String> expandableListTitle;
    private HashMap<String, List<String>> expandableListDetail;

    public CustomExpandableListAdapter(Context context, List<String> expandableListTitle,
                                       HashMap<String, List<String>> expandableListDetail) {
        this.context = context;
        this.expandableListTitle = expandableListTitle;
        this.expandableListDetail = expandableListDetail;

    public Object getChild(int listPosition, int expandedListPosition) {
        return this.expandableListDetail.get(this.expandableListTitle.get(listPosition))

    public long getChildId(int listPosition, int expandedListPosition) {
        return expandedListPosition;

    public View getChildView(int listPosition, final int expandedListPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        final String expandedListText = (String) getChild(listPosition, expandedListPosition);
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) this.context
            convertView = layoutInflater.inflate(R.layout.list_item, null);
        TextView expandedListTextView = (TextView) convertView
        return convertView;

    public int getChildrenCount(int listPosition) {
        return this.expandableListDetail.get(this.expandableListTitle.get(listPosition))

    public Object getGroup(int listPosition) {
        return this.expandableListTitle.get(listPosition);

    public int getGroupCount() {
        return this.expandableListTitle.size();

    public long getGroupId(int listPosition) {
        return listPosition;

    public View getGroupView(int listPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        String listTitle = (String) getGroup(listPosition);
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) this.context.
            convertView = layoutInflater.inflate(R.layout.list_group, null);
        TextView listTitleTextView = (TextView) convertView
        listTitleTextView.setTypeface(null, Typeface.BOLD);
        return convertView;

    public boolean hasStableIds() {
        return false;

    public boolean isChildSelectable(int listPosition, int expandedListPosition) {
        return true;

This class extends BaseExpandableListAdapter and it overrides the methods in the base class to provide the view for the ExpandableListView. getView() fills in the data into the item’s view with the given index.

package com.journaldev.expandablelistview;

import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    ExpandableListView expandableListView;
    ExpandableListAdapter expandableListAdapter;
    List<String> expandableListTitle;
    HashMap<String, List<String>> expandableListDetail;

    protected void onCreate(Bundle savedInstanceState) {
        expandableListView = (ExpandableListView) findViewById(;
        expandableListDetail = ExpandableListDataPump.getData();
        expandableListTitle = new ArrayList<String>(expandableListDetail.keySet());
        expandableListAdapter = new CustomExpandableListAdapter(this, expandableListTitle, expandableListDetail);
        expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {

            public void onGroupExpand(int groupPosition) {
                        expandableListTitle.get(groupPosition) + " List Expanded.",

        expandableListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {

            public void onGroupCollapse(int groupPosition) {
                        expandableListTitle.get(groupPosition) + " List Collapsed.",


        expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            public boolean onChildClick(ExpandableListView parent, View v,
                                        int groupPosition, int childPosition, long id) {
                                + " -> "
                                + expandableListDetail.get(
                                childPosition), Toast.LENGTH_SHORT
                return false;


In the above code we’ve implemented all the interfaces that were discussed before. For the sake of simplicity, we’ll only display a Toast with the name of the item or the state of the group for every click. But these can be easily modified to perform any other operations.

Below is our app with android expandable list view in action.

ExpandableListView, android ExpandableListView, android ExpandableListView example

Note: ExpandableListViews are scrollable by default.

This brings an end to Android ExpandableListView tutorial. You can download the final Android ExpandableListView Project from the below link.


  1. sharookh says:

    can you please help me with a bottom loading inside expandable list

  2. Deepak Kumar says:

    how can i get child view on click of expandable group

  3. George Russell says:

    Can this be adapted to show in a Simple Dialog Builder model?

  4. sari says:


    Thanks for this tutorial. i have one doubt, how can i create dynamic expandable listview. the groups and childrens data from json data(webservices). in my code two arrays getting “category and items” dynamicaly view category and corresponding items ,how can done?

  5. Jyoti says:

    is it possible to shift the position of items?
    Like according to your example I want to change the team position as first to display basketball then wants to display cricket after I want to display football Team.

    if we can do this then how could we do this? can you please explain?

  6. Alif Hasnain says:

    This was very helpful and easy to understand. Thank you.

  7. Junaidu Tanko says:

    This is really great job. THANKS

  8. Ram M says:

    Hi , how can i populate Expendable listView using Json from Volley and mysql (I have 2 tables Article and comments ), otherly how can i use dynamic data

    thank you

    1. Raja Jakkampudi says:

      Store your JSON response data into HashMap.
      The response you get is key-value pair and HashMap stores the key-value data.

      When you get respose pass that data to ExpandableListViewDataPump class.

      So it will be dynamic my dear.

  9. Maruti Nedre says:

    Hello Team,
    Thank you for the detailed information.
    A very nice example for a beginner.

  10. Nathan says:

    How can i add an expandable list on top of another expandable list

  11. Philip Webster says:

    I have implemented an ExpandableListView inside a ConstraintView, with some buttons above it.
    If the ExpandabeListView expands off the bottom screen, it does not scroll!
    Is there a solution to this?

  12. Adam says:

    Do any one know that how to paginate expandablelistview please help me.

  13. safaf says:

    SIr…Great work..I have got without any errors..I have a doubt,….can we do the same with fragment…eg,,….can we do these expandable listview completely in the fragment page

  14. Robinson says:

    Thank you so much for this post… Keep blogging please don’t stop

  15. Gautami says:

    Hi, This tutorial useful.
    But i need this expandablelistview as expand and collapse.
    That is if child layout expanded ,then all the parent layouts should collapse.
    And need to add data from API.

    1. Anupam says:

      Do this on the ExpandableListView instance:

      expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() {
          public void onGroupExpand(int groupPosition) {
                  if (lastExpandedPosition != -1
                          && groupPosition != lastExpandedPosition) {
                  lastExpandedPosition = groupPosition;
  16. Kalpesh says:

    Hi Anupam,

    Great tutorial, thanks.

    Please, could you let me know how I can add a search feature to this and when I select a child object I would like to open another activity using string.xml

  17. ganesh says:

    how can i add another one team. its not working

  18. flc says:

    Thank you very much!

  19. Daniel says:

    Hey friend, thanks a lot by the great explanation and the sources.

    You’ve saved a soul 🙂

    Tks again!

    1. Anupam says:

      Glad this helped you out Daniel.
      Always happy to save fellow souls 🙂

  20. S CD says:

    it’s not working… please help in resolving below exception.
    Returns error:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bjobs.vvtcards/com.bjobs.vvtcards.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.ExpandableListView.setAdapter(android.widget.ExpandableListAdapter)’ on a null object reference
    at Source:0)
    at android.os.Handler.dispatchMessage(
    at android.os.Looper.loop(
    at java.lang.reflect.Method.invoke(Native Method)
    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.ExpandableListView.setAdapter(android.widget.ExpandableListAdapter)’ on a null object reference

    Thanks in advance, you rock by the way. I like all your articles.

    1. Anupam says:

      You’re trying to set the adapter on a null ExpandableListView widget. Please ensure that you have set the ExpandableListView in the xml layout and have initialised it in your activity properly using findViewById.

  21. Andrew says:

    Thanks a lot for the example. It was a great help for my design.

  22. Thanks a lot for your article. But I’ve a question.
    How to add a child after last child position of group? This child was used to add a custom view?

  23. Jabes says:


    On the line “expandableListDetail = ExpandableListDataPump.getData();” the getData part returns an error saying
    “non-static method “getData” cannot be referenced from a static context”. What happened here and how to resolve? Cheers.

  24. John Coryat says:

    I figured it out. You have a minor error (?) in your code.

    In MainActivity, change:

    ExpandableListAdapter expandableListAdapter;


    CustomExpandableListAdapter expandableListAdapter;

    I believe the way you have it, the methods of the BaseExpandableListAdapter are unavailable.


    1. Anupam says:

      Hi John,
      The CustomExpandableListAdapter extends ExpandableListAdapter. So the notifyDataSetChanged method can be overridden in the class and would be available then.
      Well thought though!


  25. John Coryat says:

    Let’s say you wanted to call notifyDataSetChanged() in MainActivity. How would you go about doing that? The method isn’t available on expandableListAdapter in MainActivity.


  26. John Coryat says:

    Thanks! Very useful. Implemented in a fragment.

  27. Rahul says:

    How to add searc functionality for the above list view

    1. Anupam says:

      Add a SearchView widget in your layout.
      You need to implement Filterable interface in your adapter class and create an inner class that extends Filter class and create it’s instance. Put your filtering logic in performFiltering method inside the inner class.

      For more details refer this:

  28. Juliet says:

    Great tutorial Anupam Chugh!

    However, I advise the use of “LinkedHashMap” in stead of “HashMap” because using HashMap does not have the notion of order. When I ran my app that has an FAQ page, the order of the questions kept changing. Sometimes, I’d find the first question appearing last and vice-versa. Basically, the questions would be randomly placed within the list.

    LinkedHashMap is an implementation of Map that guarantees iteration order, so now the questions are ordered according to the order I have set, with the first question appearing first, the second question next etc etc.

    1. Anupam says:

      Thanks, Juliet. Yes, LinkedHashMap should be used when the insertion order needs to be preserved.

    2. Philipp says:

      Hi Juliet,

      I tried adding additional lists and was wondering how I could have them be in order as this was important for my project. This piece of advice helped me out a lot because I was struggling while trying to find a solution. I thought I had to change something in the way they were added to the expandablelistview. This solution worked perfectly and was easy to implement.


  29. Annie says:

    How can I turn the countries into buttons for another screen

  30. Hayat khan says:

    Inspection ‘Mismatched query and update of collection’ options
    how can I resolve this

  31. Mangesh says:

    great tutorial I like it I want do similar thing with some modification like parent should be edit text and relevant child also should be edit text and toggle button how do implement this please suggest me in this regards.
    Thanks & Regards,

  32. Hamideh says:

    thank you very much for the tutorial.

    I needed something like this for my school project but by click on any child I want to navigate to the next page of my app – so to say -that does new set of tasks. how to add this feature?I tried “performItemClick” but no achievement!

    1. Anupam says:

      onChildItemClickListener. That’s the method where you add your Intent for the next Activity.

  33. Jack Thornton says:

    Ultimately this is helpful; however, sample code is NOT a tutorial. The reader is left to try to reverse engineer why the API classes were chosen/required. It implies that the only way to fill an ExpandableListView is by using and extending BaseExpandableListAdapter and feeding it hashmaps and lists of strings; without teaching the readers the HOW and WHAT of the API classes, they are ill-equipped to create a more general solution on their own – which is what the point of a tutorial is.

    1. Anupam says:

      Hi Jack,
      To know more about the APIs you can always refer to the Google Documentation :


  34. Nick says:

    Nobody should ever be using code this bad. A nine year old could have written this. You should be ashamed to publish this.

    1. Bruce Riches says:

      Doubt it. Being so judgmental does not earn you any kudos. You could offer suggestions for improvement to the code, if you are capable of that.

      1. Pankaj says:

        Thanks Bruce for fitting reply. Some guys don’t understand that we can’t put production quality code in a tutorial. We can do that but then the tutorial will be 5 times bigger and loose focus and it’s sole purpose.

  35. Sangavi says:

    Really nice it works Perfectly fine Thank You

  36. Abubakr Ali says:

    Great tutorial Sir. Thank you

    I need to set the text to the right .. how to that ?

    1. Anupam says:

      Use the gravity attribute of the TextView

  37. Andy says:

    Thanks. Very helpful tutorial.

  38. Hi Anupam,

    Thanks, it’s a great tutorial, but I would like to implement this on Fragment instead of an Activity. There must be a slight change to this because I’ve tried and only one Group title appear and when it was expanded, no children titles were shown.

    1. Anupam says:

      Use a FrameLayout in your to instantiate the MainFragment(or whatever you name). Put the code for expandableListView in the layout for the MainFragment.

  39. eleanor says:

    Hi, using this is it possible to get the position of a child item? Thank you!

    1. Anupam says:

      Hi eleanor,
      Position of child item can be determined from the onChildClick method.
      It’s defined as :
      public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)


  40. Luis Carvajal says:

    Excuse me, when I run my app, it crashes, the Exception I got when i run it is this: “java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.widget.ExpandableListView.setAdapter(android.widget.ExpandableListAdapter)’ on a null object reference”

    1. Anupam says:

      Make sure you’ve hooked the ExpandableListView instance to its xml counterpart before you write the method setAdapter.

  41. Siva says:

    Great Tutorial can you make a tutorial using expandable list view with edit text in child list

    1. Anupam says:

      Hi Siva,
      Why do you need that?

  42. ccmads says:

    Thanks for the tutorial!

    I’m making a FAQ list for my app, i am wondering is it possible to load the parent (the question as title) and child (answer as content) string from string array list in the xml (which will be much easier to add new item without editing the java)? Maybe a array for question and another one for answer, and after loaded into the list, the answer will show in their respective question.

    Like this in the xml:




  43. Lovely Singh says:

    Very easy and fine tutorial for beginners. Thank You..

    1. Anupam says:

      Glad that you liked it

  44. Jimmy says:


    Great Article and thanks for the help.

    Well I implemented this in my project but am having the Expandable List inverted along with the child items. Can you suggest

    1. Anupam says:

      Use LinkedListHashMap instead. It’ll preserve your order.

  45. Ryan says:


    Nice tutorial

    How is the parent and child arranged or sorted out?

    1. Anupam says:

      Hi Ryan,
      The group header and child are sorted out in this case since an ArrayList displays data in chronological order. A HashMap is used to map the respective group header with its child.


  46. Gielany Rosal says:

    Hi i would like to ask, how can i put the arrow down in the right position? Thank you in advance for the help.

    1. Anupam says:

      Hi Gielany Rosal,
      Add an ImageView to the right of the group title in the group header view and set the image resource. (Download it from google or use android:src=”@android:drawable/arrow_up_float”, android:src=”@android:drawable/arrow_down_float”). Toggle the image when the group is expanded or collapsed.
      Hide the left indicator set it as null as shown below.

      Alternative Solution:
      Override the method onWindowFocusChanged as shown below.

      public void onWindowFocusChanged(boolean hasFocus) {
      if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
      } else {
      In this case the arrow would look distorted.
      I'd say go for the first solution.


  47. sanyog says:

    Hello freinds,

    My quesry is can we add data in expandable list view dynamically through sqlite database, if yes, olease help me with the same. Thanks.

    1. Anupam says:

      Store the ArrayLists as JSON Strings in the SQLite database. Convert them to ArrayList and vice-versa using Gson Library.

  48. Mohanraj says:

    Thank you Very much, How can do this for populating array from JSON API, i don’t have idea how to populate array values from the JSON. Kindly give some references. Thanks in Advance Mohanraj.

    1. Anupam says:

      Hi Mohanraj,
      Try iterating over the JSONArray using a for loop. Use ArrayLists to populate data from JSONObjects. Essentially you can keep an ArrayList to store the header values, another to store child data for each header. Use a HashMap to store key value pairs. Ideally, the group header name should be the key and the child ArrayList should be it’s mapped value.


  49. iamlazynic says:

    Great tutorial!
    I am try these and encountered a problem.

    exlView = (ExpandableListView) findViewById(;
    exlDetail = ExlDataPump.getData();
    exlTitle = new ArrayList(exlDetail.keySet());
    exlAdapter = new ExlAdapter(this, exlTitle, exlDetail);

    There brought me an error : invoke setAdapter on null object. What’s wrong???

    1. Anupam says:

      Hi iamlazynic,
      Seems like exlTitle is empty. Try debugging by printing the fields/nested objects of exlTitle and exlDetail.


  50. Daniel Silva says:

    Great tutorial! Thank you!

  51. vetdam says:

    Thanks man, great details and greate code!

  52. jaya says:

    Very good tutorial

  53. elham says:

    very neatly put! Thank you

  54. harsha says:

    how to start an activity if group have no child items and when i clicked on group and if another group having childs if click on group open childs and based on child clik navigate to other views android

    1. Anupam says:

      Hi Harsha,
      I understand that you are looking for a way to start an activity by clicking a group that has no children. Right?
      There is a setOnGroupClickListener() method that you can invoke and possibly define the intent to the next activity.


Leave a Reply

Your email address will not be published. Required fields are marked *

Generic selectors
Exact matches only
Search in title
Search in content