Search This Blog

Thursday 5 July 2012

Android Expandable ListView simple Example in android.

Android Expandable ListView simple Example in android. We are aware about android most powerful feature ListView. We can handle ListView click event e.g clicking on ListView row, we can start a new activity or what ever we want to do. But it some how strange to many developer, clicking on ListView row it should expand and show more details in spite of opening a new Activity and we can shrink row of ListView after reading details information. This is feature known as ExpandableListView in android. ExpandableListView is pre-define widget in android . and much similar to android ListView.
So here we go for ExpandableListView Simple Example with source code at the end of this article.
ExpandableListView include some steps to create one simple sample Create one fresh project and Extends ExpandableListActivity inspite of Activity public class MainActivity extends ExpandableListActivity

ExpandableListView include two kind of data one for Group Item and One for child of corresponding Group item so lets have a look how prepare data for ExpandableListView 

public void setGroupData() {
  groupItem.add("TechNology");
  groupItem.add("Mobile");
  groupItem.add("Manufacturer");
  groupItem.add("Extras");
         }

     ArrayList<String> groupItem = new ArrayList<String>();
     ArrayList<Object> childItem = new ArrayList<Object>();

     public void setChildGroupData() {
  /**
   * Add Data For TecthNology
   */
  ArrayList<String> child = new ArrayList<String>();
  child.add("Java");
  child.add("Drupal");
  child.add(".Net Framework");
  child.add("PHP");
  childItem.add(child);

  /**
   * Add Data For Mobile
   */
  child = new ArrayList<String>();
  child.add("Android");
  child.add("Window Mobile");
  child.add("iPHone");
  child.add("Blackberry");
  childItem.add(child);
  /**
   * Add Data For Manufacture
   */
  child = new ArrayList<String>();
  child.add("HTC");
  child.add("Apple");
  child.add("Samsung");
  child.add("Nokia");
  childItem.add(child);
  /**
   * Add Data For Extras
   */
  child = new ArrayList<String>();
  child.add("Contact Us");
  child.add("About Us");
  child.add("Location");
  child.add("Root Cause");
  childItem.add(child);
     }

Now Data is ready to showing inside ExpandableListView. Now just like a simple list view we need one adapter to bind data to ExpandableListView. But this time we will use BaseExpandableListAdapter in place of BaseAdapter as it provide a way to create child of a Group when we expand it Finally we need two Layout one to showing Group Row and One two showing Child Row inside ExpandableListView Main Hurdle How to perform Click on child of ExpandableListView? ExpandableListView provide OnChildClickListener but for unknown reason, I am not able to perform child click event using this.
So i created one another way.while creating Child View we will perform click Listener over there in getChildView method of Adapter So now times to introduce with Code step by Step

Step 1) Change your Main Activity code to as following 



package com.multilayerexpandable;

import java.util.ArrayList;

import android.app.ExpandableListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.Toast;

public class MainActivity extends ExpandableListActivity implements
  OnChildClickListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ExpandableListView expandbleLis = getExpandableListView();
  expandbleLis.setDividerHeight(2);
  expandbleLis.setGroupIndicator(null);
  expandbleLis.setClickable(true);

  setGroupData();
  setChildGroupData();

  NewAdapter mNewAdapter = new NewAdapter(groupItem, childItem);
  mNewAdapter
    .setInflater(
      (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE),
      this);
  getExpandableListView().setAdapter(mNewAdapter);
  expandbleLis.setOnChildClickListener(this);
 }

 public void setGroupData() {
  groupItem.add("TechNology");
  groupItem.add("Mobile");
  groupItem.add("Manufacturer");
  groupItem.add("Extras");
 }

 ArrayList<String> groupItem = new ArrayList<String>();
 ArrayList<Object> childItem = new ArrayList<Object>();

 public void setChildGroupData() {
  /**
   * Add Data For TecthNology
   */
  ArrayList<String> child = new ArrayList<String>();
  child.add("Java");
  child.add("Drupal");
  child.add(".Net Framework");
  child.add("PHP");
  childItem.add(child);

  /**
   * Add Data For Mobile
   */
  child = new ArrayList<String>();
  child.add("Android");
  child.add("Window Mobile");
  child.add("iPHone");
  child.add("Blackberry");
  childItem.add(child);
  /**
   * Add Data For Manufacture
   */
  child = new ArrayList<String>();
  child.add("HTC");
  child.add("Apple");
  child.add("Samsung");
  child.add("Nokia");
  childItem.add(child);
  /**
   * Add Data For Extras
   */
  child = new ArrayList<String>();
  child.add("Contact Us");
  child.add("About Us");
  child.add("Location");
  child.add("Root Cause");
  childItem.add(child);
 }

 @Override
 public boolean onChildClick(ExpandableListView parent, View v,
   int groupPosition, int childPosition, long id) {
  Toast.makeText(MainActivity.this, "Clicked On Child",
    Toast.LENGTH_SHORT).show();
  return true;
 }
}

 

Step2) Create two XML Layout one for Group row and one for Childe Row of ExpandableListView Group Row XML Layout 

 

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/textView1" 
android:layout_width="wrap_content" android:layout_height="60dp" android:layout_marginLeft="5dp" android:drawableRight="@drawable/plusminus" android:gravity="center_vertical" android:text="@string/hello_world" android:textColor="#FFFFFF" android:padding="10dp" android:textSelectHandleLeft="@string/hello_world" 
android:textSize="14sp"
 android:textStyle="bold" /> 

Child Row XML Layout 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:background="@android:color/black"
    android:clickable="true"
    android:orientation="vertical"
    android:paddingLeft="40dp"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="39dp"
        android:gravity="center_vertical" >

        <ImageView
            android:id="@+id/childImage"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_margin="5dp"
            android:background="@drawable/ic_launcher"
            android:contentDescription="@string/hello_world" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            android:text="@string/hello_world"
            android:textColor="#FFFFFF"
            android:textSize="14sp"
            android:textStyle="bold" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@android:color/white" />

</LinearLayout>

 

Step 3) Finally Create one New class for binding data inside ExpandableListView 

 


package com.multilayerexpandable;

import java.util.ArrayList;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckedTextView;
import android.widget.TextView;
import android.widget.Toast;

@SuppressWarnings("unchecked")
public class NewAdapter extends BaseExpandableListAdapter {

 public ArrayList<String> groupItem, tempChild;
 public ArrayList<Object> Childtem = new ArrayList<Object>();
 public LayoutInflater minflater;
 public Activity activity;

 public NewAdapter(ArrayList<String> grList, ArrayList<Object> childItem) {
  groupItem = grList;
  this.Childtem = childItem;
 }

 public void setInflater(LayoutInflater mInflater, Activity act) {
  this.minflater = mInflater;
  activity = act;
 }

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

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

 @Override
 public View getChildView(int groupPosition, final int childPosition,
   boolean isLastChild, View convertView, ViewGroup parent) {
  tempChild = (ArrayList<String>) Childtem.get(groupPosition);
  TextView text = null;
  if (convertView == null) {
   convertView = minflater.inflate(R.layout.childrow, null);
  }
  text = (TextView) convertView.findViewById(R.id.textView1);
  text.setText(tempChild.get(childPosition));
  convertView.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    Toast.makeText(activity, tempChild.get(childPosition),
      Toast.LENGTH_SHORT).show();
   }
  });
  return convertView;
 }

 @Override
 public int getChildrenCount(int groupPosition) {
  return ((ArrayList<String>) Childtem.get(groupPosition)).size();
 }

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

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

 @Override
 public void onGroupCollapsed(int groupPosition) {
  super.onGroupCollapsed(groupPosition);
 }

 @Override
 public void onGroupExpanded(int groupPosition) {
  super.onGroupExpanded(groupPosition);
 }

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

 @Override
 public View getGroupView(int groupPosition, boolean isExpanded,
   View convertView, ViewGroup parent) {
  if (convertView == null) {
   convertView = minflater.inflate(R.layout.grouprow, null);
  }
  ((CheckedTextView) convertView).setText(groupItem.get(groupPosition));
  ((CheckedTextView) convertView).setChecked(isExpanded);
  return convertView;
 }

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

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

}


So Screen Shot of Complete Guide will be like




Download Source Code

38 comments:

  1. I have problem while loading child list with different layout for each group, http://stackoverflow.com/q/12314793/501859
    I have to load some 7 different child layouts. Can you suggest, how can i do it more efficiently.

    ReplyDelete
  2. "Download Source Code" file deleted. I cant download source code of this project.

    ReplyDelete
    Replies
    1. Yes ..its deleted.Thank you for pointing this issue. I will update link as soon as possible i can.Please keep visiting this

      Delete
    2. I think..now its working fine...Please check it once

      Delete
  3. Works fine. Thanks.

    but, How can i achieve the same thing within a fragment? I mean i want an expandableListView within a fragment.

    ReplyDelete
  4. works fine. thanks. is it possible to implement an expandable list view in a fragment?

    ReplyDelete
  5. Hello,

    I have one doubt in the ExpandableListView, I am creating ExpandableListView to display the Reviews & Ratings. So in that I am having only one Group in which I am displaying text like " 2 Reviews & Ratings". I gone through your code and accordingly made some changes for my case. Now my ExpandableListView is showing only the header text but when i click on it it does not show me anything. I am using BaseExpandableListAdapter as I want to customize it. I have posted my code on SO and here is the link of it. I am sure that I am making mistake somewhere in the adapter but not able to get that. So can you please kindly help me.

    SO question - http://stackoverflow.com/questions/12879389/expandablelistview-is-not-working-properly-baseexpandablelistadapter-issue

    ReplyDelete
    Replies
    1. hi Keyur...Currently i am busy with my schedule. So i can not help on your specific problem.

      Delete
  6. Your blogs and information attracts me to come back again n again.
    one click root

    ReplyDelete
  7. I am getting solution for my dynamic data from your code but unable to manipulate with image url data . Could you please help me how to show image at child of relevent GroupData.

    ReplyDelete
  8. I'm wondering if there's any chance I can add a listener to child Nodes, because I need customized actions when clicking on the child.
    Simple example : AlertDialog that displays the selected child's string.
    Thank you :)

    ReplyDelete
    Replies
    1. Hi, you can set click listener to child as well. Let if Expandable ListView object is exipandabl then set like this exipandabl.setOnChildClickListener(new OnChildClickListener() {
      @Override
      public boolean onChildClick(ExpandableListView parent, View v,
      int groupPosition, int childPosition, long id) {
      return false;
      }
      });

      Delete
  9. hi,Tofeeq
    I have multiple views in expandable list but i cant able to save the values of views.
    Views could be EditText,checkbox etc.
    Please help me if u can...

    ReplyDelete
    Replies
    1. You can save and perform click in getChildView method of BaseExpandableListAdapter

      Delete
  10. I like this because it is nice for dynamic data.But I want to ask a question that I can't answer exactly.
    Is there a performance difference between the above code (for dynamic data) and simple example following (for static data)? http://androidexperiences.wordpress.com/2011/09/21/how-to-create-a-custom-expandablelistview-2/
    I mean the above code contains List() objects which I think ,is more complex than simple arrays.
    I haven't tested yet but let me know if you can answer.
    I want a smooth UI for android.
    Thanks

    ReplyDelete
    Replies
    1. I did not get your point about dynamic data..!!!!!!!!

      Delete
  11. The method isChildSelectable in the Adapter is returning false. Thats why the child row is not clickable in the activity.

    ReplyDelete
  12. AOA TOFEEQ,

    I have recently used your blog and it is really helpful and contains a lot of information and guides for new android users. I am planning to use the expandable list and the example above was really helpful to me. THANKS....
    I have a question regarding above expandable list. Question is that

    IS IT POSSIBLE TO ASSIGN DIFFERENT "ICON" TO EACH ITEM IN A GROUP?
    or
    IS IT POSSIBLE TO ASSIGN DIFFERENT "COLOR" TO EACH ITEM IN A GROUP?

    Please Show a small example of that......

    THANK YOU,
    MUHAMMAD

    ReplyDelete
    Replies
    1. Thank you..you can take one array of images and there are two method getChildView for customizing child row and getGroupView to customize your group row. Its just like ListView. These method will return position and you can use image from your array

      Delete
  13. Oh sorry, my problem regarding stringBuilders was solved. There was human error in my file. Thanks anyway

    ReplyDelete
  14. hi .
    what is the use of "NewAdapter" and it said that (NewAdapter cannot be resolve?

    ReplyDelete
    Replies
    1. NewAdapter used to bind data inside ExpandableListView. Refer Step 3 in above article. If you do no have this class in code copy from there

      Delete
  15. thanks for that. i understand it now.
    i copied already the codes and edit some of the it no problem detected. but i'm having a problem on running it on the emulator. i think i got a mistake in coding it to ANDROIDMANIFEST.XML







    ReplyDelete
  16. Really useful, thanks. I'm trying to put views into the child items instead of strings and it's not working. Can you help?

    ReplyDelete
    Replies
    1. getChildView() allow you to inflate complete layout in child row and you can use any required data in it. First see how to create custom ListView using Image and Text. If you know that you can easily change in child

      Delete
  17. Hello,

    I created a class for the menu and a class for the adapter, it works.
    Click on a child works with the adapter class and not the class menu. Do you have an idea to make it work.
    Now I would like to start a business from the choice of a child. What code and put or place?
    Thank you for your contribution

    ReplyDelete
  18. hello,
    In my application which I develop this expandable list is one activity which I want to put a logo that exist in all screens.
    Where is the place to add this logo? where do I make the change?

    thanks,
    Marina

    ReplyDelete
    Replies
    1. As far as i understand you, you want to change logo on every child of Expandable ListView. You have look into method getChildView() ,Take one layout for android child of ListView and set Background of ImageView

      Delete
  19. Hi Where exactly to add the method OnChildClickListener on the above code ?? So that every each child item have to load a specific activity ??

    ReplyDelete
    Replies
    1. Hi, For some reason, onChildClickListener was not working, when i develop tutorial. So i made one workaround, I set the click event inside Adapter Class.
      see
      convertView.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) {
      Toast.makeText(activity, tempChild.get(childPosition),
      Toast.LENGTH_SHORT).show();
      }
      });

      I am showing one toast you can do whatever you want

      Delete

Feedback always help in improvement. If you have any query suggestion feel free to comment and Keep visiting my blog to encourage me to blogging

Android News and source code