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
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
Child Row XML Layout
So Screen Shot of Complete Guide will be like
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
I have problem while loading child list with different layout for each group, http://stackoverflow.com/q/12314793/501859
ReplyDeleteI have to load some 7 different child layouts. Can you suggest, how can i do it more efficiently.
"Download Source Code" file deleted. I cant download source code of this project.
ReplyDeleteYes ..its deleted.Thank you for pointing this issue. I will update link as soon as possible i can.Please keep visiting this
DeleteI think..now its working fine...Please check it once
DeleteThis was of great help. Cheers :)
ReplyDeleteWorks fine. Thanks.
ReplyDeletebut, How can i achieve the same thing within a fragment? I mean i want an expandableListView within a fragment.
works fine. thanks. is it possible to implement an expandable list view in a fragment?
ReplyDeleteYes, its possible to implement it with fragment. See my Fragment Example with action bar tab
DeleteHello,
ReplyDeleteI 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
hi Keyur...Currently i am busy with my schedule. So i can not help on your specific problem.
DeleteYour blogs and information attracts me to come back again n again.
ReplyDeleteone click root
Thank you..
DeleteI 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.
ReplyDeleteCan you explain your issue?
DeleteI'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.
ReplyDeleteSimple example : AlertDialog that displays the selected child's string.
Thank you :)
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() {
Delete@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
return false;
}
});
hi,Tofeeq
ReplyDeleteI 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...
You can save and perform click in getChildView method of BaseExpandableListAdapter
DeleteVery Helpful Thanks
ReplyDeleteYour welcome..Keep visiting my blog
DeleteI like this because it is nice for dynamic data.But I want to ask a question that I can't answer exactly.
ReplyDeleteIs 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
I did not get your point about dynamic data..!!!!!!!!
DeleteThe method isChildSelectable in the Adapter is returning false. Thats why the child row is not clickable in the activity.
ReplyDeleteAOA TOFEEQ,
ReplyDeleteI 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
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
DeleteTHANKS......
DeleteOh sorry, my problem regarding stringBuilders was solved. There was human error in my file. Thanks anyway
ReplyDeletehi .
ReplyDeletewhat is the use of "NewAdapter" and it said that (NewAdapter cannot be resolve?
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
Deletethanks for that. i understand it now.
ReplyDeletei 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
Really useful, thanks. I'm trying to put views into the child items instead of strings and it's not working. Can you help?
ReplyDeletegetChildView() 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
DeleteHello,
ReplyDeleteI 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
What is Menu class?
Deletehello,
ReplyDeleteIn 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
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
DeleteHi Where exactly to add the method OnChildClickListener on the above code ?? So that every each child item have to load a specific activity ??
ReplyDeleteHi, For some reason, onChildClickListener was not working, when i develop tutorial. So i made one workaround, I set the click event inside Adapter Class.
Deletesee
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