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.
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"/>
Table Of Contents
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 -->
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 -->
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.
6. padding: padding attribute is used to set the padding from left, right, top or bottom.
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 -->
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.
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:
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.
Premium Project Source Code:
Sir i have implemented your code and got result,but the listview is expanded by default…i need to expand it on clicking the groupitem..but the cde you have given is making to expand by default..pls help me to fix it..ch
How to change scrollbar color of childgroup at level 3 in Expandable listview
Great article, thank you so much
how to go to another activity on clicking child items in android
sir how to go to another activity after clicking child button.
hey can you help me?
i want to make apps like this,
when i click a button in a child i can change a group of the child background color to green
can we change a header backgroud color after we clik its child?
Not able to download the code. Please help?
Please email to info@abhiandroid.com and we will send you the code directly.
Where should i call the expandAll method ??
I called the expandAll() from onCreate but it should only the drop down icon on expand mode .I cannot see the list.. Please help!
What a nice and understandable tutorial. Thank you so much for your kind tutorial 🙂
i use this code and the header of application is lost… how to show it again?
Please, can you tell me how I can change the background colour of the header/title?
Thanks
Hi, THanks very much for the detailed explanation. Please, can you tell me how to change the header background colour?
thnkx sir.
sir kya hum new actvity pr ja skte hain jb hum kisi list view pr click kren.
Awesome dude. Loved this tutorial. Helped me a lot
thank you a lot… you are very good i love you
keep trying …. bro. keep trying
because, we are also keep trying
Hi, how can i implement expandable listview with table layout in child layout? please help.Thanks
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.
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?
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?
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).
Okay Thanks!
hello . THANKS A LOT . YOU ARE BESSST!!!
@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.
Please refer to Adapter tutorial to understand it https://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.
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?
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 ..
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.
Hello sir how can i reuse it in my project i means how i make another View which items are changed .plz help me sir Thanks
Excelente tutorial mi lenguaje es español pero lo entendi perfectamente gracias.
How can I open different Intent by press the child element?
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.
Thank you sir. It’s very helpful.
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