SyntaxHighlighter

Tuesday, September 25, 2012

How to work with android ExpandableListView

Hi all today I am going to show, How to work with android expandable list view.This is very much like list view but here you can group you list items.So you can expand/collapse those group and see what ever you want.So implementing this is bit difficult than normal list view.

First I will show you basic figure that we going to implement today.
layout
And this is project structure.
project structure

Here I do not describe all details and I am very much focusing on key things that we have to do.So please following steps.
1) First we create Child.java represent our list item.
package com.android.guide.expandablelistview;
public class Child {
 public String chiledId;
 public String childName;
 public Child(String chiledId, String childName) {
  super();
  this.chiledId = chiledId;
  this.childName = childName;
 }
 public String getChiledId() {
  return chiledId;
 }
 public void setChiledId(String chiledId) {
  this.chiledId = chiledId;
 }
 public String getChildName() {
  return childName;
 }
 public void setChildName(String childName) {
  this.childName = childName;
 }
}

2) Then we want layout to preview our list item. So we create child_view.xml in res/layout for that.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >
    <TextView
     android:id="@+id/textViewChildName"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center"
     android:textAppearance="?android:attr/textAppearanceSmall" />

</LinearLayout>

3)Then create Group.java class. This class going to use as our list view group header and also it holds child class(list items).
package com.android.guide.expandablelistview;
import java.util.ArrayList;
public class Group {
 public String groupId;
 public String groupName;
 public ArrayList childrens;
 public Group(String groupId, String groupName,
   ArrayList childrens) {
  super();
  this.groupId = groupId;
  this.groupName = groupName;
  this.childrens = childrens;
 }
 public String getGroupId() {
  return groupId;
 }
 public void setGroupId(String groupId) {
  this.groupId = groupId;
 }
 public String getGroupName() {
  return groupName;
 }
 public void setGroupName(String groupName) {
  this.groupName = groupName;
 }
 public ArrayList getChildrens() {
  return childrens;
 }
 public void setChildrens(ArrayList childrens) {
  this.childrens = childrens;
 } 
}

4)Then we need xml view for our group header so we create group_view.xml in res/layout folder like following.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >
    <TextView
     android:id="@+id/textViewGroupName"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center"
     android:textAppearance="?android:attr/textAppearanceMedium" />

</LinearLayout>

5) Then we come to most important part ExpandableListAdapter.We create this adapter extending BaseExpandableListAdapter. This is special ListAdapter for ExpandableListView. So create this class and implement as following.
package com.android.guide.expandablelistview;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;

/**
 * @author Sanath Nandasiri
 * this is expandable list adapter
 */
public class ExpandableListAdapter extends BaseExpandableListAdapter { 
 LayoutInflater inflater;
 
 /*list of group */
 private ArrayList<Group> groups;
 public ExpandableListAdapter(Context context,ArrayList<Group> groups) {
 super();
  this.groups=groups;
  inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 }
 /**
  * @param child
  * @param group
  *  use for adding item to list view
  */
 public void addItem(Child child,Group group) {
  if(!groups.contains(group)) {
   groups.add(group);
  }
  int index=groups.indexOf(group);
  ArrayList<Child> ch=groups.get(index).getChildrens();
  ch.add(child);
  groups.get(index).setChildrens(ch);
 }
    public Child getChild(int groupPosition, int childPosition) {
     ArrayList<Child> ch=groups.get(groupPosition).getChildrens();
        return ch.get(childPosition);
    }   
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }    
 @Override
 public int getChildrenCount(int groupPosition) {
  ArrayList<Child> ch=groups.get(groupPosition).getChildrens();
  return ch.size();
 } 
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
            View convertView, ViewGroup parent) {
     Child child= (Child) getChild(groupPosition,childPosition);
     TextView childName=null;
     if(convertView==null) {
         convertView=inflater.inflate(R.layout.child_view, null);         
       }
     childName=(TextView) convertView.findViewById(R.id.textViewChildName);
     childName.setText(child.getChildName());
  return convertView;
    }
    public Group getGroup(int groupPosition) {
        return groups.get(groupPosition);
    }
    public int getGroupCount() {
        return groups.size();
    }
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
            ViewGroup parent) {
     TextView groupName = null;
     Group group=(Group) getGroup(groupPosition);
     if(convertView==null) {
       convertView=inflater.inflate(R.layout.group_view, null);        
     }
     groupName=(TextView) convertView.findViewById(R.id.textViewGroupName);
     groupName.setText(group.getGroupName());
        return convertView;
    }
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
    public boolean hasStableIds() {
        return true;
    }
}

Here you can  see two method called getChildView and getGroupView here we inflate our child_view and group_view layout.In getGroupView method we can get current group position.Using that we can get current group data and inflate group view.In getChildView also we can get current child position.Using that we can get child data and inflate child view.

6) Finally you can bring all things together in MainActivity. So implement like following. 
package com.android.guide.expandablelistview;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.ExpandableListView;

public class MainActivity extends Activity {

 /*our expandable adapter */
 ExpandableListAdapter expandableListAdapter;

 /*expandable list*/
 ExpandableListView expandableListView;

 /*list items*/
 ArrayList<Group> groups=new ArrayList<Group>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     /*genarate data for list view*/
     genarateData();

     /*instantiate adapter with our item list*/
     expandableListAdapter=new ExpandableListAdapter(this, groups);

     /*we get list view*/
        expandableListView=(ExpandableListView) findViewById(R.id.expandableListView);

        /*set adapter to list view*/
        expandableListView.setAdapter(expandableListAdapter);

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    //Generate dummy data for list view
    public void genarateData() {
     Group group;
     for (int i = 0; i < 10; i++) {
      
      ArrayList<Child> childrens=new ArrayList<Child>();
      childrens.clear();
      Child child;
   for (int j = 0; j < 5; j++) {
    child=new Child(""+j, "I am Child "+j);
    childrens.add(child);
   }
   group=new Group(""+i, "I am Group "+i, childrens);
   groups.add(group);
  }
    }
}
Then run your example. It will look like following
collapsexpand



You can download source code here

Please comment on any problem and further details.

Hope you will learn some thing and give me a feedback.