Friday, September 17, 2010

ExpandableListView on Android

ListView is pretty widely used. There are situations when you would like to group/categorize your list items. To achieve such a thing on Android, you would probably use the ExpandableListView. The data to the ExpandableListView is supplied by a special kind of adapter called the SimpleExpandableListAdapter which extends the BaseExpandableListAdapter.

As with any other widget on Android, you are free to customize the widgets as per your needs. Here, I will show how to create such a custom list adapter for the ExpandableListView.

For this example, I want to show a list of vehicles with their names. Also, I want to group them according to their category.

I have 4 classes.
1. Vehicle : The parent class for the rest.
2. Car: Extends the Vehicle class.
3. Bus: Extends the Vehicle class.
4. Bike: Extends the Vehicle class.

I have a method called getRandomVehicle(String name) which returns a random vehicle instance setting the name that I pass. The vehicle can be a Bus, Car or a Bike. Its completely random.

In the ExpandableListAdapter, (the custom adapter), there's a method called addItem(Vehicle vehicle), which manages the groups and their children.

In the SampleActivity, I have initialized a blank ExpandableListAdapter and set it to the list view. Now, I start a thread, which gets a random vehicle after every 2 seconds, and adds it to the adapter, and calls the adapter to notify that the data has changed.

There are a few methods, in the ExpandableListAdapter, which you should go through carefully. I have two layout files, group_layout.xml and child_layout.xml which are used as the layout for the group views and the child views of the ExpandableListView.

There you go, you have a custom ExpandableListView. You can find the full source code for this example here, ready to run.

There are some more methods that you might be interested in, like, how to change the "arrow icon" for the group views(official doc link), or how to expand or collapse a group at will, or how to handle specific events like group collapsed or group expanded. Read the docs on ExpandableListView.

106 comments:

  1. Hello Kumar,

    Thanks for posting your tutorials, they are very useful.

    I'm trying to implement CheckedTextView under ExpandableListView, however Checking a box in one group can cause a random box from another group to check or uncheck once I expand or Collapse a group, I'm using SimpleExpandableListAdapter, do I need to cutomise my own adapter? and do I need to keep track of each state of checkbox using something like SharedPreference?

    I'm new to Android and have no idea how to make a custom ExpandableListAdapter, what should I be looking at in order to solve the phenomenon above? getChildView()? and onGroupExpand/Collpase()?

    It will be greatly appreciated if you could give me a hint, thanks a lot in advance.

    ReplyDelete
  2. Well, it's not specific to Expandable List View. If you can make the same work with a Simple List View, it will give you an idea how to solve this issue.

    ReplyDelete
  3. Thanks Kumar, I used SharedPreferences to keep track of the state of each checkbox and make sure the state is correct in getChildView(), thanks for the tip.

    ReplyDelete
  4. Hello Kumar

    Any idea of displaying no icon when no child in parent list item?

    ReplyDelete
  5. For not diplaying the icon, you can set the icon by using the setIndicator method. I don't really understand what you mean by "when no childin parent".

    ReplyDelete
  6. Kumar-
    Thanks for the post...helped tons getting my development going.
    But have a quick question-
    I have a ragged hierarchy of parents and children.
    In that there are some parents that have 5 children...and some parents have 0 children.

    The expandableListView displays the "Expand/Collpase" icon even if there are no children.

    Question-
    Is there a way to hide the icon for only those Parents(rows) that have no children?

    ReplyDelete
  7. How to load webview efficiently in an expandable list view

    ReplyDelete
  8. Hi, Bibek these are really nice tutorial. Keep posting.

    ReplyDelete
  9. The group_layout.xml and child_layout.xml point to the same file.

    ReplyDelete
  10. Good post!

    just wanted to pour some info in ...The problem that @atur pointed out will still occur with this code. However, the solution to the problem is to write a custom adapter extending BaseExpandableAdapter.

    I found another guy's blog which addresses this issue : http://mylifewithandroid.blogspot.com/2010/12/expandable-list-and-checkboxes.html

    - Adastrossi

    ReplyDelete
  11. Thanks a million for the post :-) Exactly what I was looking for.

    ReplyDelete
  12. Thanks for the post! Its been very helpful.

    ReplyDelete
  13. Good post thanks,i have one question though whi didn't you use the ExpandableListActivity ?

    ReplyDelete
  14. You can use that too. I normally avoid using ListActivities... :)

    ReplyDelete
  15. I'm a beginner in android,can i know why you avoid using them ?
    They seem practical to deal with user events.

    ReplyDelete
  16. Well, Normally, I would have a few more controls on the activity other that just the List. It could still work, but it's just a personal choice, I would say. :)

    ReplyDelete
  17. Hi Kumar,
    I am really appreciates for your useful post. I have one question at below.
    How can i use custom font at this list view? Actually I have tried some coding at ExpandableListAdapter.java. I put like this inside "public View getGroupView"

    TextView txt = (TextView) findViewById(R.id.tvGroup);
    Typeface font = Typeface.createFromAsset(getAssets(), "Chantelli_Antiqua.ttf");
    txt.setTypeface(font);

    The Error is getAssets() is cannot use inside ExpandableListAdapter. If you don't mind, please give me some ideas. Thanks millions Bro!

    ReplyDelete
  18. How can i add list view as child?? i would like to add n number of expandablelistview depending on the number of requirements..any suggestions on how to do this

    ReplyDelete
  19. Hi All, I have a problem, i have made a expandable list, and i have a view on child list now i want access that view on Clicking event on parent list.
    Please help me.
    Thank you

    ReplyDelete
  20. Child List? You mean the ListView's items?

    ReplyDelete
    Replies
    1. hi kumar how do you resolve "resource not found exception -resource is not a drawable"....i have used 4 png files .

      Delete
    2. Where have you put them? Try cleaning your project.

      Delete
  21. yes, when we expand the list then it shows the child list, and this child has some view,like image button. i have to access that image button on clicking of parent list.

    i want access that child's view on the following code

    expandedList.setOnGroupClickListener(new OnGroupClickListener()
    {

    @Override
    public boolean onGroupClick(ExpandableListView arg0, View arg1, int arg2, long arg3)
    {

    Toast.makeText(getBaseContext(), "Group clicked ", Toast.LENGTH_SHORT).show();

    return false;
    }
    });

    ReplyDelete
  22. You should be setting listeners inside your adapter class while you are creating/inflating the imageView.

    ReplyDelete
  23. I have done this work, i have inflated the child_Layout inside the listener but it gives null pointer exception.
    i have added the following code inside the listener.

    LayoutInflater infalInflater = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View convertView = infalInflater.inflate(R.layout.child_row, null);

    ImageView tv = (ImageView) convertView
    .findViewById(R.id.imageView2);
    tv.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View arg0) {
    Intent intent = new Intent(ExpList.this, DemoActivity.class);
    startActivity(intent);
    }
    });

    ReplyDelete
  24. Where does it give Exception? Are you sure that the image view's ID is imageView2 ?

    ReplyDelete
  25. yes,id is imageView2. how can i share my whole source code to you??

    ReplyDelete
  26. it gives exception when i clicked on parent list

    ReplyDelete
  27. Intent intent = new Intent(context, DemoActivity.class);

    You should be passing the context to the adapter, and use that context here like this.

    Send it to my mail if you want, but I can only check it by tonight.

    ReplyDelete
  28. thank you very much.
    please give me your mail id.

    ReplyDelete
  29. Check coomar(dot)101(at)gmail(dot)com

    ReplyDelete
  30. Sir, I have a problem that I want to copy videos from my Desktop Pc's MyVideos Directory to sdcard of android emulator through code. But I unable to do that. I had searched it many times on the web but can't find the exact solution. Can you help me regarding this?

    ReplyDelete
  31. Hello Kumar,
    I have a problem in Expandable list. I want to access Child_row's xml file in parent list click event.could u provide the code for the same.
    Thanks.

    ReplyDelete
  32. I didn't exactly get what you want. That might not be possible to explain well if I don't exactly know what you are trying to achieve.

    ReplyDelete
  33. Hello Sir,
    How can we make expandable list with help of simple list view. please provide the source code for the same.
    Thank you.

    ReplyDelete
  34. @Himanshu: What exactly do you mean by simple list view? Expandable list is different from simple list view.

    ReplyDelete
  35. @Kumar: Actually, I have a problem in Expandable list, when we expand any parent group, it has child list, and in every child row it has a button. but i am unable to give event to that button.
    so i was asking that can we make and expandable list with the help of simple list view??

    please give me right solution to do this task.
    how it can be done? is there any alternative ??

    ReplyDelete
  36. In the Adapter class, attach the event to the button/image. For reference:

    http://code.google.com/p/myandroidwidgets/source/browse/trunk/Phonebook/src/com/abeanie/PhonebookAdapter.java

    ReplyDelete
  37. Sir, I need to set the twolinelistitem to ExpandableListview as child, Is it possible? if possible please send me the code

    ReplyDelete
  38. sir can you plz tell me how can i place deferent images on the each groupview of expandable listview....

    ReplyDelete
  39. Thanks for that tutorial!
    I was wondering - is it also possible to have a double-expandable list? My situation is as follows:

    -SystemPlatform-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    -SystemPlatform-Object
    --- Game-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    etc.

    Could you give me a hint how I could implement something like this? I want the SystemPlatform objects to be expandable (that already works if I use your tutorial) but in the childs of the Game objects also have expandable children.

    Thanks a lot for your help!

    ReplyDelete
  40. I haven't tried this. But, it seems to be a little difficult to achieve this.

    ReplyDelete
  41. Hi Kumar,
    I want to develop similar ExpandableListview to an Accordion Menu. When I click a parent bar it extracts. If the different is this:
    A parent's child has a list but other parent's child has a image etc.
    How do I do this?
    Thanks

    ReplyDelete
  42. Thanks for that tutorial!


    -SystemPlatform-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    -SystemPlatform-Object
    --- Game-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    ------ Cheat-Object
    ------ Cheat-Object
    --- Game-Object
    ------ Cheat-Object
    etc.

    did you tried this...........

    ReplyDelete
  43. Great Tutorial! Thanks!

    I would like to use this using a database back end. I have defined a cursor to populate the list. Specifically, if I use a text field to display the item list (adapter.addItem()), how can retrieve the database record number?

    Would you provide a suggestion how to 'toast' the database record number.

    ReplyDelete
  44. Thanks for posting this tutorial. It was of immense help. However, I found a small problem in the main.xml. While declaring expandable list, android requires the use of the id that is declared in android just as we use for list:


    I kept getting runtime exceptions since I was having id as listView.

    ReplyDelete
  45. @linisax: If your activity extends ExpandableListActivity, you will need to have the id different, in the android namespace, else, if your activity extends the basic activity, this sample would run fine.

    ReplyDelete
  46. @Van: Your cursor would have an _id field, so you should bind the _id list to your data structure. And you should be able to do that.

    ReplyDelete
  47. Thanks for that small detail. It is easy to over-look it.
    I found a new problem with expandablelistview and adapters. So I retrieve the values for the group arraylist and the children arraylist using a thread. However, simply calling notifyDataSetChanged() on the adapter did not refresh my listview. It showed as empty. (my code is laid out very similar to your example. The only difference is the data modelling which is coming from a server in my case).

    So I wrote a helper function in the adapter class that manully updated the group and children arraylists to the values received from server. After that calling notifyDataSetChanged(), refreshed my list. I am not sure if this is a good programming practice but it worked.

    ReplyDelete
  48. Thanks you, Kumar. Your example has been extremely helpful to me. I needed a list view years and months. Since every year has the same months (of course!) there was no need to supply the months to the adapter so I simplified it to this:

    public class MyExpandableMonthListAdapter extends BaseExpandableListAdapter {
    private String[] children = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };

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

    private ArrayList groups;

    public MyExpandableMonthListAdapter(Context context, ArrayList groups) {
    this.groups = groups;
    }


    public Object getChild(int groupPosition, int childPosition) {
    return children[childPosition];
    }

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

    public int getChildrenCount(int groupPosition) {
    return children.length;
    }
    ...
    ...
    }

    And then I initialize it with:

    years = new ArrayList(Arrays.asList( "2011","2010","2009","2008" ));
    MyExpandableMonthListAdapter myAdapter = new MyExpandableMonthListAdapter(this, years);

    ReplyDelete
  49. @Martin: Thanks: This would work. :)

    ReplyDelete
  50. Kumar,

    I only have 1 child view for each group view, which is inflated from a layout .xml file. I wish to animate the child view so that when the child item is displayed, the list item below it slids down. I am trying the following, but the animation doesn't show as expected. I have added the following to the getChildView(), just before I return the child view:

    Animation anim = AnimationUtils.loadAnimation(
    MyExpandableList.this, R.anim.translate);
    v.setAnimation(anim);

    Here's is my translate.xml:





    Thanks for your help.

    Ani.

    ReplyDelete
  51. Hmm, I would probably write up a sample project for animating this. Not sure when, but say in a few days.

    ReplyDelete
  52. How can we put expandable list in tabs. No multiple inheritance in java?
    I am new to android.
    If you can point me to some tutorila.

    ReplyDelete
  53. Umm, There's no multiple inheritance.

    But, your activity could extend the TabActivity, and use the ExpandableListViews in layouts directly. So, in this case, you need to extend the ExpandableListActivity.

    ReplyDelete
  54. Hi, thanks for the tutorials, it's great having people like yourself help everyone else.

    This expandable listview is similar to what i'm looking for but doesnt quite have the functionality that i'm after. I have a custom slidingdrawer class that i've got to a stage where it acts how i would like however i'm now looking to stack them, so that the handles appear one on top of eachother, almost acting like an accordion menu. Any tips on where to look to get this to work? I know that there are issues with the containing framelayout etc =s

    ReplyDelete
  55. @Marc: I haven't tried that yet. Sounds interesting though. :)

    ReplyDelete
  56. thanksssssssss........

    you are the best!!!!!

    ReplyDelete
  57. Thank you for that tutorial and the code. It helped a lot to create an own expandable listView

    ReplyDelete
  58. Hi All :)
    Have you any idea how to (if it is possible) develop an expandable listView where each group header stays pinned to the top until it is pushed up by the next group view?
    @Agamousy

    ReplyDelete
  59. @Agamousy: You mean, the iPhone style? Haven't tried that yet. :)

    ReplyDelete
  60. Hi kumar

    how to make search menu so we can searching content of the group

    thank you

    ReplyDelete
  61. thanx for give step by step process of expendable listview...............

    ReplyDelete
  62. I've tried to swap random to filling from database. I'm stuck somehow. I get the blank activity page. Dont know why. I got the data properly from database, objects are created, but nothing happens... there is description on a stackflow
    http://stackoverflow.com/questions/8488575/filling-expendablelistview-with-database-entries

    ReplyDelete
  63. @Xylian: You are probably missing something. Without more details it wont be clear as to what the problem is.

    ReplyDelete
  64. please tell me .. how to add layout and component i.e. button ,textview in PAGE CURL EFFECT

    ReplyDelete
  65. Hi, Thanks for the post. really helpful. Can you tell me ow u replaced the icon(the icon which shows that the list is expanded or not) with ur custom icon? and the svn link for readonly dosen seem to work. Please help

    ReplyDelete
  66. @rakendu: I just updated he link to the official doc. It's pretty straightforward. Use a state-list drawable for that with states as mentioned in the doc.

    A sample:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:state_expanded="true"
    android:drawable="@drawable/down_arrow" />
    <item
    android:drawable="@drawable/right_arrow" />
    </selector>

    ReplyDelete
  67. Hi there all! How do you deal with having a group header but no childs???im using this example for building a dialog with the expandable list and its working fine, except when i try to expand the group with no childs i get an error regarding the children arraylist of arraylist. in this case there's no childs in position 3, so it gives an out of bounds exception. Also is there a way to prevent the icon to change/ and the position to expand since thre's no childs?

    regards,

    ReplyDelete
  68. Hi there all! How do you deal with having a group header but no childs???im using this example for building a dialog with the expandable list and its working fine, except when i try to expand the group with no childs i get an error regarding the children arraylist of arraylist. in this case there's no childs in position 3, so it gives an out of bounds exception. Also is there a way to prevent the icon to change/ and the position to expand since thre's no childs?

    regards,

    ReplyDelete
  69. IS there a way to deal with groups with no childs??this example gives an outofbound exception in the children arraylist of arraylist in the adapter if you try to exapnd a ground that has no childs. Also is there a way to prevent the icon to change position and also prevent to expand in this case at all?

    regards,

    ReplyDelete
  70. Im having errors when theres no childs and i expand a group with no childs. Out lf bound exceptions.

    ReplyDelete
    Replies
    1. It's designed not to show the header if there are no children.

      Delete
    2. Hi there ive emailed you. I adapted yout code but thats not happens if i add a group with no children.

      Regards.

      Delete
  71. Im using the adapter in the code you posted but its not doing that...Also is there a way to manually do the expanding/collapsing as in define a button do that instead of pressing any area of the group row???i want to also select the group as an option like the childs....

    ReplyDelete
  72. has anyone tried that with the code successfullyu. please can anyone post thier running code here. the code available on the site recomended dosnt provide a gud class structure.

    ReplyDelete
  73. I have used BaseExpandableListAdapter for a project.We have a requirement to highlight group row selection.so that user can see for himself the row selected.How is this possible

    ReplyDelete
  74. I have used BaseExpandableListAdapter for a project.We have a requirement that the Group row should remain hightlighted to show user his selection.How is this possible

    ReplyDelete
  75. Hi, I have used the above code to make an expandable list view..Although , the code attaches drawlable objects to the parent group..My aim to to make a an expandableview for a form , i.e , the children to be attached to each group is an .xml layout. How do I do that? Any suggestions please?

    ReplyDelete
  76. Hi Kumer, really nice tutorial. I have only one Question. My Ex-Listview doesnt show groups with no entries. Do you have any hint for me how to display them? Thank you so far!

    ReplyDelete
    Replies
    1. The default Ex-ListView is designed to do that. I haven't tried to make it work like that. So, right now, I can't say anything.

      Delete
  77. Hi Kumar ,

    I have 5 groups in my expandableviewlist. I want to populate the child of each group with a different XML layout. Is that possible?Hope it is clearer now..

    ReplyDelete
    Replies
    1. Sure. You could do that. In the getChildView method you could inflate a different xml depending on what kind of the child you want to show.

      Delete
  78. Hi Kumar,

    Just wanted to thank you for your valuable work, helped a lot :)

    Cheers, good luck !

    ReplyDelete
  79. hai I want sample example for dropbox listview in android plz do that.

    ReplyDelete
    Replies
    1. What exactly do you mean by dropbox listview?

      Delete
  80. what did u tell i wrote but it gaves nullpointexception whatwill i do
    but u r tutorial very nicfe

    ReplyDelete
  81. group_layout.xml could not be found.

    ReplyDelete
    Replies
    1. I can see it here.. http://code.google.com/p/myandroidwidgets/source/browse/trunk/CustomExpandableListView/res/layout/child_layout.xml

      Delete
  82. how code exception in expandable list ? please u write a example code ..

    ReplyDelete
  83. Hello Kumar, Nice 2 know U..
    I'm from indonesia, thanks for ur tutorial that's very helpfull..
    hehe..

    ReplyDelete
  84. Thanks Kumar for your tutorial, thats very useful..
    I'm from indonesia, glad 2 know U..

    ReplyDelete
  85. Hi this is very nice tutorials...thanks for post this tutorial..i have one doubts.
    I have a problem , ı want to add different child for respective groups in expandableList like that;

    - OrderInfo
    - payment_method
    - total
    - CustomerInfo
    - firstname
    - lastname
    i know Is it possible?...but i can't develop this..can anyone give me some sample code please ?or give me some idea...

    ReplyDelete
  86. Hello Kumar,

    this is a very nice post.

    However I am trying to understand how I can animate the expand/collapse of the group. So, I want to touch on the group and expand the list but with animation. Similarly, when tapping again on the group to collapse but with animation.

    Do you have any idea of how to achieve this?

    Thanks

    ReplyDelete
  87. Hello Sir,

    Its very nice tutorial on ExpandableListView and very well explained. But I am in need of your help in this. I am having 1 expandablelistview in my app with only 1 group. I am displaying review and ratings inside it. I follow your tutorials but somehow as my case is different my list is not displayed. It only shows me the header of the expandablelistview, when i click to see the details its not calling the childView method of the adapter. Here is the link of SO of my question with full details and source code. If you can please have a look on it once and help me then it would be very great for me.

    Regards
    Keyur

    ReplyDelete
  88. Hello All,

    I want n-level of expandable.

    How to do for same.

    Thanks,

    ReplyDelete
    Replies
    1. I can't really think of a situation where it would be required. I guess, the UI needs a second opinion if you really have such a requirement.

      Delete
  89. Hey Kumar,

    I am quite new to android programming, and there are so many listeners i don`t know how to pick the right one.

    i want each parend zu have a button, which adds a child node to its sektion.

    but wen i add a onclicklistener to the button, i don`t know how to get the section where the button was :(

    ReplyDelete
  90. Greate!
    I really wanted customized expandable ListView..
    Thanks...

    ReplyDelete