ExpandableListView With Example In Android Studio

In Android, ExpandableListView is a View that shows items in a vertically scrolling two level list. Different from the listview by allowing two level groups which can individually be expanded to show its children. Each group can be expanded or collapsed individually to show or hide its children items.

ExpandableListView in Android

We can attach listeners events to the ExpandableListView to listen for OnClick or any other events on the Group or the individual children.  Adapters are used to supply or control the data that will be displayed in an ExpandableListView.

Important Note: You cannot use the value wrap_content for the height attribute of a ExpandableListView in XML if the parent’s size is not strictly specified. In other words we mean if the parent were ScrollView then you could not specify wrap_content since it can be of any length. However, you can use wrap content if the ExpandableListView parent has a specific size, such as 200 pixels.

ExpandableListView code in XML:

<ExpandableListView
android:id="@+id/simpleExpandableListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>

ExpandableListView In XML Android


Attributes of ExpandableListView In Android

Now let’s we discuss about some important attributes that helps us to configure a ExpandableListView in XML file(layout).

1. id: id is an attribute used to uniquely identify a Expandable List View.

<ExpandableListView
android:id="@+id/simpleExpandableListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/> <!--  id of an attribute used to uniquely identify a expandable list view -->

2. divider: This is a drawable or color to draw between different group list items.

Below we draw red color divider between different group items.

<ExpandableListView
android:id="@+id/simpleExpandableListView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:divider="#f00"
android:dividerHeight="1dp" /> "/> <!--  red color divider with 1dp height between the groups items of  expandable list view -->

Divider in ExpandableListView Android

3. dividerHeight: This specify the height of the divider between group list items. This could be in dp ( density pixel ), sp(scale independent pixel) or px ( pixel ).

In above example of divider we also set the divider height 1dp between the list items. The height should be in dp, sp or px.

4. listSelector: This property is used to set the selector of the expandable list View. It is generally orange or Sky blue color mostly but you can also define your own custom color or an image as a list selector as per your design.

Below selector color is green, when you select any list item then that item’s background color is green.

<ExpandableListView
android:id="@+id/simpleExpandableListView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:divider="#f00"
android:dividerHeight="1dp"
android:listSelector="#0f0" /> <!--  green color for the list selector item -->

listSelector in ExpandableListView Android

5. childDivider: This is a drawable or color to draw between different child list items of a expandable list view.

Below we draw green color divider between different child items of a group.

<ExpandableListView
    android:id="@+id/simpleExpandableListView"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:divider="#f00"
    android:dividerHeight="1dp"
    android:childDivider="#0f0" />  <!--  green color divider between the child items of  expandable list view -->

The below image is from the ExpandableListView example which is explained at the end of this post. In this we have set green color as Child divider and red color as divider. The reason we have used this example image because we need fill data using Adapter to show you childDivider attribute in action.

childDivider in ExpandableListView Android

6. padding: padding attribute is used to set the padding from left, right, top or bottom.

  • paddingRight: set the padding from the right side of the expandable list view.
  • paddingLeft: set the padding from the left side of the Progress bar.
  • paddingTop: set the padding from the top side of the expandable list view.
  • paddingBottom: set the padding from the bottom side of the expandable list view.
  • Padding: set the padding from the all side’s of the expandable list view.

Below we set the 50dp padding from all the side’s of the expandable list view.

<ExpandableListView
android:id="@+id/simpleExpandableListView"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:divider="#f00"
android:dividerHeight="2dp"
android:childDivider="#0f0"
android:padding="50dp" /> <!--  50 dp padding from all the sides of a expandable list view -->

padding in ExpandableListView Android


Adapter Used In ExpandableListView In Android:

An adapter is a bridge between UI component and data source that helps us to fill data in UI component. It holds the data and send the data to Adapter view then view can takes the data from the adapter view and shows the data on different views like as ExpandableListView or other Views. The implementation of this interface will provide access to the data of the children (categorized by groups), and also instantiate views for the children and groups.

In Android for supplying data in an ExpandableListView following adapters are used.

1. ExpandableListAdapter
2. BaseExpandableListAdapter
3. SimpleExpandableListAdapter

Now we explain these three adapters in detail:

1. ExpandableListAdapter:

ExpandableListAdapter is an Adapter that links a ExpandableListView with the underlying data. The implementation of this interface will provide the data for the children and also initiate the views for the children and groups.  For customization of list we need to implement ExpandableListAdapter in our custom adapter.

Below is the example code of ExpandableListAdapter in which we create CustomAdapter class and then implements ExpandableListAdapter in that class.

public class CustomAdapter implements ExpandableListAdapter {
@Override
public void registerDataSetObserver(DataSetObserver observer) {

}

@Override
public void unregisterDataSetObserver(DataSetObserver observer) {

}

@Override
public int getGroupCount() {
return 0;
}

@Override
public int getChildrenCount(int groupPosition) {
return 0;
}

@Override
public Object getGroup(int groupPosition) {
return null;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}

@Override
public long getGroupId(int groupPosition) {
return 0;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}

@Override
public boolean hasStableIds() {
return false;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
return null;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
return null;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}

@Override
public boolean areAllItemsEnabled() {
return false;
}

@Override
public boolean isEmpty() {
return false;
}

@Override
public void onGroupExpanded(int groupPosition) {

}

@Override
public void onGroupCollapsed(int groupPosition) {

}

@Override
public long getCombinedChildId(long groupId, long childId) {
return 0;
}

@Override
public long getCombinedGroupId(long groupId) {
return 0;
}
}

Read ExpandableListAdapter Tutorial With Example In Android Studio for more details.

2. BaseExpandableListAdapter:

BaseExpandableListAdapter is a base class for the expandable list adapter used to provide data and Views from some data to ExpandableListView. For Creating a custom ExpandableListView we need to create a custom class and then extends BaseExpandableListAdapter class in that class.

Below is an example code of BaseExpandableListAdapter in which we create custom adapter class and then extends BaseExpandableListAdapter in that class.

public class CustomAdapter extends BaseExpandableListAdapter {

@Override
public int getGroupCount() {
return 0;
}

@Override
public int getChildrenCount(int groupPosition) {
return 0;
}

@Override
public Object getGroup(int groupPosition) {
return null;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
return null;
}

@Override
public long getGroupId(int groupPosition) {
return 0;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
return 0;
}

@Override
public boolean hasStableIds() {
return false;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
return null;
}

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
return null;
}

@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return false;
}
}

Read BaseExpandableListAdapter With Example In Android Studio for explanation of all these function.

3. SimpleExpandableListAdapter:

SimpleExpandableListAdapter is an adapter that is used to map the static data to group and child views defined in our XML ( layout ) file. We can separately specify the data backing to the group as a List of Maps. Each entry in a ArrayList corresponds to one group in the Expandable List. The maps contains the data for each row. We can also specify an XML file that defines the views used to display a group, and a mapping from keys in the Map to specific views. This process is similar for a child, except it is one level deeper so the data backing is specified as a List<list>, where the first List is corresponds to the group of the child and the second List corresponds to the position of the child within that group, and finally the Map holds the data for the particular child.

public SimpleExpandableListAdapter (Context context, List<? extends Map<String, ?>> groupData, int groupLayout, String[]groupFrom, int[] groupTo, List<? extends List<? extends Map<String, ?>>> childData, int childLayout, String[] childFrom, int[] childTo)

Read SimpleExpandableListAdapter tutorial for explanation of all these parameter.


ExpandableListView using BaseExpandableListAdapter Example In Android Studio

Below is the example of ExpandableListView in android where we display an expandable list with subject name and their topics. In this example we display subject names as Group items and their topic names as child items for a particular group. In this we implement setOnChildClickListener() and setOnGroupClickListener() events and whenever a user clicks on a child or a group item the name of the item is displayed by using a Toast.

Below you can download code, see final output and step by step explanation of Example in Android Studio:

Download Code

SignUp! To Download ExpandableListView Example Source Code

FREE Download Now  >>
100% tested, easy instant download and import in Android Studio
close-link

ExpandableListView Example In Android Studio

Step 1: Create a new project and name it ExpandableListViewExample.

Step 2: Open res -> layout ->activity_main.xml (or) main.xml and add following code:

In this step we open an XML file and add the code for displaying a ExpandableListView by using its different attributes.

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

    <ExpandableListView
        android:id="@+id/simpleExpandableListView"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:divider="#f00"
        android:childDivider="#0f0"
        android:dividerHeight="1dp" />

</RelativeLayout>

Step 3: Create a new xml file for group items Open res -> layout -> group_items.xml and add following code:

In this step we add the code for displaying a TextView subject names.

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

    <TextView
        android:id="@+id/heading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="35sp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textStyle="bold" />

</LinearLayout>

Step 4: Create a new xml file for group items Open res -> layout -> child_items.xml and add following code:

In this step we add the code for displaying two TextView i.e. one for sequence of topics and another for topic name

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

    <TextView
        android:id="@+id/sequence"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:paddingLeft="35sp"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/childItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@id/sequence"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

Step 5: Open   src -> package -> MainActivity.Java

In this step we open MainActivity and add the code to initiate the ExpandableListView and add the data to lists for displaying in an ExpandableListView using model classes and then set the adapter which fills the data in the ExpandableListView. In this we implement setOnChildClickListener() and setOnGroupClickListener() events. Whenever a user clicks on a child or a group item the name of the item is display by using a Toast.

package example.abhiandroid.expandablelistviewexample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.LinkedHashMap;

public class MainActivity extends AppCompatActivity{

    private LinkedHashMap<String, GroupInfo> subjects = new LinkedHashMap<String, GroupInfo>();
    private ArrayList<GroupInfo> deptList = new ArrayList<GroupInfo>();

    private CustomAdapter listAdapter;
    private ExpandableListView simpleExpandableListView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // add data for displaying in expandable list view
        loadData();

        //get reference of the ExpandableListView
        simpleExpandableListView = (ExpandableListView) findViewById(R.id.simpleExpandableListView);
        // create the adapter by passing your ArrayList data
        listAdapter = new CustomAdapter(MainActivity.this, deptList);
        // attach the adapter to the expandable list view
        simpleExpandableListView.setAdapter(listAdapter);

        //expand all the Groups
        expandAll();

        // setOnChildClickListener listener for child row click
        simpleExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                //get the group header
                GroupInfo headerInfo = deptList.get(groupPosition);
                //get the child info
                ChildInfo detailInfo =  headerInfo.getProductList().get(childPosition);
                //display it or do something with it
                Toast.makeText(getBaseContext(), " Clicked on :: " + headerInfo.getName()
                        + "/" + detailInfo.getName(), Toast.LENGTH_LONG).show();
                return false;
            }
        });
        // setOnGroupClickListener listener for group heading click
        simpleExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                //get the group header
                GroupInfo headerInfo = deptList.get(groupPosition);
                //display it or do something with it
                Toast.makeText(getBaseContext(), " Header is :: " + headerInfo.getName(),
                        Toast.LENGTH_LONG).show();

                return false;
            }
        });


    }

    //method to expand all groups
    private void expandAll() {
        int count = listAdapter.getGroupCount();
        for (int i = 0; i < count; i++){
            simpleExpandableListView.expandGroup(i);
        }
    }

    //method to collapse all groups
    private void collapseAll() {
        int count = listAdapter.getGroupCount();
        for (int i = 0; i < count; i++){
            simpleExpandableListView.collapseGroup(i);
        }
    }

    //load some initial data into out list
    private void loadData(){

        addProduct("Android","ListView");
        addProduct("Android","ExpandableListView");
        addProduct("Android","GridView");

        addProduct("Java","PolyMorphism");
        addProduct("Java","Collections");

    }



    //here we maintain our products in various departments
    private int addProduct(String department, String product){

        int groupPosition = 0;

        //check the hash map if the group already exists
        GroupInfo headerInfo = subjects.get(department);
        //add the group if doesn't exists
        if(headerInfo == null){
            headerInfo = new GroupInfo();
            headerInfo.setName(department);
            subjects.put(department, headerInfo);
            deptList.add(headerInfo);
        }

        //get the children for the group
        ArrayList<ChildInfo> productList = headerInfo.getProductList();
        //size of the children list
        int listSize = productList.size();
        //add to the counter
        listSize++;

        //create a new child and add that to the group
        ChildInfo detailInfo = new ChildInfo();
        detailInfo.setSequence(String.valueOf(listSize));
        detailInfo.setName(product);
        productList.add(detailInfo);
        headerInfo.setProductList(productList);

        //find the group position inside the list
        groupPosition = deptList.indexOf(headerInfo);
        return groupPosition;
    }

}

Step 6: Create a New Class Open -> package – > GroupInfo.Java and add the following code.

In this step, we create a class for setting and getting the group item name and child items info according to a particular group. GroupInfo is a model class used to set the name of the group item and child items information from your main activity and then get the information within Adapter class. Finally set the value to ExpandableListView.

package example.abhiandroid.expandablelistviewexample;

import java.util.ArrayList;

public class GroupInfo {

    private String name;
    private ArrayList<ChildInfo> list = new ArrayList<ChildInfo>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ArrayList<ChildInfo> getProductList() {
        return list;
    }

    public void setProductList(ArrayList<ChildInfo> productList) {
        this.list = productList;
    }

}

Step 7: Create a New Class Open -> package – > ChildInfo.Java and add the following code.

In this step, we create a class for setting and getting the name and sequence for the child items. ChildInfo is a model class used to set the name of the child item and the sequence of the child item from your main activity and then get the name and sequence within adapter class. Finally set the value to expandable list view.

package example.abhiandroid.expandablelistviewexample;

public class ChildInfo {

    private String sequence = "";
    private String name = "";

    public String getSequence() {
        return sequence;
    }

    public void setSequence(String sequence) {
        this.sequence = sequence;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Step 8: Create a New Class Open -> package – > CustomAdapter.Java and add the following code.

In this step, we create a CustomAdapter class and then extends BaseExpandableListAdapter in that class. Finally set the data in the ExpandableListView from GroupInfo and  ChildInfo model class.

package example.abhiandroid.expandablelistviewexample;

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;


/**
 * Created by Gourav on 08-03-2016.
 */
public class CustomAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<GroupInfo> deptList;

    public CustomAdapter(Context context, ArrayList<GroupInfo> deptList) {
        this.context = context;
        this.deptList = deptList;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        ArrayList<ChildInfo> productList = deptList.get(groupPosition).getProductList();
        return productList.get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                             View view, ViewGroup parent) {

        ChildInfo detailInfo = (ChildInfo) getChild(groupPosition, childPosition);
        if (view == null) {
            LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = infalInflater.inflate(R.layout.child_items, null);
        }

        TextView sequence = (TextView) view.findViewById(R.id.sequence);
        sequence.setText(detailInfo.getSequence().trim() + ". ");
        TextView childItem = (TextView) view.findViewById(R.id.childItem);
        childItem.setText(detailInfo.getName().trim());

        return view;
    }

    @Override
    public int getChildrenCount(int groupPosition) {

        ArrayList<ChildInfo> productList = deptList.get(groupPosition).getProductList();
        return productList.size();

    }

    @Override
    public Object getGroup(int groupPosition) {
        return deptList.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return deptList.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isLastChild, View view,
                             ViewGroup parent) {

        GroupInfo headerInfo = (GroupInfo) getGroup(groupPosition);
        if (view == null) {
            LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inf.inflate(R.layout.group_items, null);
        }

        TextView heading = (TextView) view.findViewById(R.id.heading);
        heading.setText(headerInfo.getName().trim());

        return view;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

}

Output:

Now run the App and you will see main topics and sub-topics listed in ExpandableListView.

  • Is this article helps you understand?
  • YES   NO

18 thoughts on “ExpandableListView With Example In Android Studio”

  1. I’m being really thankful to you for this precious tutorial.I have searched a example code for hours since I’m a new bee to android development but i couldn’t find this kind of working code and this is the best one on the internet.

  2. I’m trying to do this with checkboxes instead testview in my child itens. I made it, but when i check some checkboxes other child gets checked… How can i fix it?

  3. I tried the example of this Expandable List View exactly as given above.
    I am only getting the Android Group that too without its Child Items.

    Could You help?

    1. Please download code, extract and import in Android Studio. It will work and compare with your code. If you still face problem please contact us(link in the top right).

  4. @Md. Ruhul Amin
    Can you please explain me in detail with modified code may be. I am new to these Adapters and coding. I wish if i could open a new page in the app after clicking on the topics of the child list.

    1. Please refer to Adapter tutorial to understand it http://abhiandroid.com/ui/adapter . Regarding understanding my advice is code it side by side. The more you will code again & again the better you will understand. Regarding opening new page on clicking topics you will need to create separate Activity for each child items and use child item click listener. In future we will write tutorial on it.

  5. Hello,
    I use switchCompact as child. But When I click any group’s switchcompact, other group’s swicthCompact also click on and vise versa. For example if I click on first group’s third child, second group’s second child click on also. Can anybody help me?

  6. I have one table in table i have 5 colum . id , productName , productPrice , productQuantity ,ShopsName i ‘m stuck about a week .. how can i show shopName on gruopView and other item of row as a child view .. but when i insert row again with same shop name new row item automatically insert inside previous GroupView that have same shop name .. is it Possible Please help me Sir .. Advance Thanks Hope you solve my problem ..

  7. Sir, is it safe to call intents on non activity class? I mean if you called it from the Adapter then you cannot call an intent to another activity. Could you extend your tutorial how to do it. When you clicked the child then it goes to another activity. I’m having problems because I am calling an activity from the adapter.

    1. In getChildView(int groupPosition, int childPosition, boolean isLastChild,View view, ViewGroup parent) function we have position for every item so perform setOnClickListener event on item in this function and send/open an intent according to child item’s position.

  8. That was really nice tutorial with multiple examples of adapters, but it was slightly confusing with child names and grp names . still it is the best on the internet. thank you for this tutorial

Leave a Reply

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



Continue Reading Below Tutorial

Subscribe and get access to the latest android tutorials, freebies, and lots more!

Android Developer Money eBook
One More Step...

Enter your email and I'll send you a FREE copy of Android Dev Dollaring eBook:
Send Me This eBook >>
We hate SPAM and promise to keep your email address safe.
close-link

SignUp! To Download ExpandableListView Example Source Code

FREE Download Now  >>
100% tested, easy instant download and import in Android Studio
close-link

Download Your Free Copy

Download this free eBook and Learn:
1. Different approach developer use to earn through App business
2. Learn how Android Developer can generate passive income
3. Job is not the only option and you can choose freelancing
Send Me This eBook >>
close-link
One More Step...

Enter your email and I'll send you a FREE copy of Android Dev Dollaring eBook:
Send Me This eBook >>
We hate SPAM and promise to keep your email address safe.
close-link