Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A 3 level expandable list view
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ExpandableListView android:id="@+id/mainList"
android:layout_width="match_parent"
android:layout_height="match_parent"></ExpandableListView>
</RelativeLayout>
<?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="100dp"
android:background="@android:color/holo_orange_dark"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/eventsListEventRowText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="20dp"
android:textColor="@android:color/white"
android:textSize="18sp"/>
</LinearLayout>
<?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:background="@android:color/holo_blue_bright"
android:padding="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/eventsListEventRowText"
android:paddingLeft="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="14sp"/>
</LinearLayout>
<?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:padding="10dp"
android:orientation="vertical"
android:background="@android:color/holo_green_dark">
<TextView
android:id="@+id/eventsListEventRowText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="24sp"/>
</LinearLayout>
package net.stf.threelevelexpandablelistview;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.TextView;
/**
* New and improved. Feel free to contact me if you have any questions.
*/
public class ThreeLevelExpandableListView extends AppCompatActivity {
public static final int FIRST_LEVEL_COUNT = 6;
public static final int SECOND_LEVEL_COUNT = 4;
public static final int THIRD_LEVEL_COUNT = 20;
private ExpandableListView expandableListView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
expandableListView = (ExpandableListView) findViewById(R.id.mainList);
expandableListView.setAdapter(new ParentLevel(this));
}
public class ParentLevel extends BaseExpandableListAdapter {
private Context context;
public ParentLevel(Context context) {
this.context = context;
}
@Override
public Object getChild(int arg0, int arg1) {
return arg1;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
SecondLevelExpandableListView secondLevelELV = new SecondLevelExpandableListView(MainActivity.this);
secondLevelELV.setAdapter(new SecondLevelAdapter(context));
secondLevelELV.setGroupIndicator(null);
return secondLevelELV;
}
@Override
public int getChildrenCount(int groupPosition) {
return SECOND_LEVEL_COUNT;
}
@Override
public Object getGroup(int groupPosition) {
return groupPosition;
}
@Override
public int getGroupCount() {
return FIRST_LEVEL_COUNT;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_first, null);
TextView text = (TextView) convertView.findViewById(R.id.eventsListEventRowText);
text.setText("FIRST LEVEL");
}
return convertView;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
public class SecondLevelExpandableListView extends ExpandableListView {
public SecondLevelExpandableListView(Context context) {
super(context);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//999999 is a size in pixels. ExpandableListView requires a maximum height in order to do measurement calculations.
heightMeasureSpec = MeasureSpec.makeMeasureSpec(999999, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public class SecondLevelAdapter extends BaseExpandableListAdapter {
private Context context;
public SecondLevelAdapter(Context context) {
this.context = context;
}
@Override
public Object getGroup(int groupPosition) {
return groupPosition;
}
@Override
public int getGroupCount() {
return 1;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_third, null);
TextView text = (TextView) convertView.findViewById(R.id.eventsListEventRowText);
text.setText("SECOND LEVEL");
}
return convertView;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_second, null);
TextView text = (TextView) convertView.findViewById(R.id.eventsListEventRowText);
text.setText("THIRD LEVEL");
}
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return THIRD_LEVEL_COUNT;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
}
@peswanibros

This comment has been minimized.

Copy link

peswanibros commented Aug 25, 2015

HI I've set OnChildClickListener but it does not work. Can you please help?

@wasimdivum

This comment has been minimized.

Copy link

wasimdivum commented Jan 8, 2016

First Thanks for nice code..I would like to know how will we populate list dynamically.

@ParthiAndroid

This comment has been minimized.

Copy link

ParthiAndroid commented Feb 17, 2016

Nice Tutorial. Works charm. Thanks for code

@ajith-kp-1892

This comment has been minimized.

Copy link

ajith-kp-1892 commented May 4, 2016

How to populate Dynamically values..??pls help me out...

@jigsandi

This comment has been minimized.

Copy link

jigsandi commented May 11, 2016

At third level we have multiple child with image view , the issue is that when image loading finish third child row added multiple time.

@shripaljadhav

This comment has been minimized.

Copy link

shripaljadhav commented Dec 9, 2016

How to use Dynamical Values...?
and ClickListner

@Sarosh-Madara

This comment has been minimized.

Copy link

Sarosh-Madara commented Feb 10, 2017

Is it works fine in ScrollView?

@Shrikant-B

This comment has been minimized.

Copy link

Shrikant-B commented Mar 10, 2017

can you explain same in terms of list and model object instead of integer count

@ashokbg

This comment has been minimized.

Copy link

ashokbg commented Mar 17, 2017

please can you explain by using ArrayList as dataresource ..

@shagung-optimus

This comment has been minimized.

Copy link

shagung-optimus commented Apr 10, 2017

for SecondLevelAdapter group view is shown for group postion 0 only. Please tell me why it is not called for other positions

@anandtaji

This comment has been minimized.

Copy link

anandtaji commented Jun 2, 2017

For dynamic make we should use recursion...

@talhahasanzia

This comment has been minimized.

Copy link

talhahasanzia commented Jun 22, 2017

I have created a repo to add dynamic data in this list, it works fine until level 3. Kindly look at this repo (https://github.com/talhahasanzia/Three-Level-Expandible-Listview) and see if you can contribute. The code is not very optimized since my primary goal is to get the list working.
@shripaljadhav @shripaljadhav @wasimdivum @ShrikantBadwaik-007 @ashokbg

@anandtaji I have tried recursive approach (calling other adapter in getChildView() ) and it failed badly.

@ShadabQuaiser

This comment has been minimized.

Copy link

ShadabQuaiser commented Jun 28, 2017

Thanks alot for such a nice code.....it really helped me out.

@MeMurillo

This comment has been minimized.

Copy link

MeMurillo commented Jul 13, 2017

Muchas gracias!

@carlosismael4

This comment has been minimized.

Copy link

carlosismael4 commented Aug 29, 2017

Thank u so much!! lml

@tribitinfotech

This comment has been minimized.

Copy link

tribitinfotech commented Sep 21, 2017

Hello sir, I have implement this code and working as well. but I have issue getting double time sub group to show selected child.
I have modify some in my code. Could you please check that Why I am getting that?

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeasureSpec,
                MeasureSpec.AT_MOST);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(totalHeight,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

This changes is in CustExpListview.

if (isSelected) {
            mCustExpListview.expandGroup(1);
}

This changes is in Parend Adapter getChildView method.

@VarshaRGowda

This comment has been minimized.

Copy link

VarshaRGowda commented Nov 20, 2017

First Thanks for the nice code. .and
I would like to know how to do a miltilevel expandable listview?
Please help me out...

@dhaval-zaptech

This comment has been minimized.

Copy link

dhaval-zaptech commented Jan 12, 2018

hi,
Cool sample..!!
i used this classes, and added dynamic data to it.
I faced two issues;

  1. texts gets random; common and well known listview problem; solved by adding viewholder and setTag-getTag approach.
  2. when all three levels of a item is opened; and list is scrolled, and then scrolled backed; thrid level of list gets collapsed (Mostly due to re-rendering of listview cells)

Is there any way to maintain, collapsed and expanded state for thrid level?

Thanks in advance.

@tiwarikk

This comment has been minimized.

Copy link

tiwarikk commented Jul 10, 2018

how to click event on 3rd level child please check sir
Thanks i am waiting your response

@tabetuba

This comment has been minimized.

Copy link

tabetuba commented Jul 25, 2018

It means u are a master developer in android
thanks for your tutorial

@vikasrajput007

This comment has been minimized.

Copy link

vikasrajput007 commented Sep 15, 2018

its a hundreds dollar code

@bereket-kassahun

This comment has been minimized.

Copy link

bereket-kassahun commented May 4, 2019

nice code, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.