Skip to content

Instantly share code, notes, and snippets.

@st-f
Last active August 15, 2023 22:52
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save st-f/2b2a838d3f0258c5c33f to your computer and use it in GitHub Desktop.
Save st-f/2b2a838d3f0258c5c33f to your computer and use it in GitHub Desktop.
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;
}
}
}
@mpeswani
Copy link

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

@wasimdivum
Copy link

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

@ParthiAndroid
Copy link

Nice Tutorial. Works charm. Thanks for code

@ajith-kp-1892
Copy link

ajith-kp-1892 commented May 4, 2016

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

@jigsandi
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
Copy link

How to use Dynamical Values...?
and ClickListner

@Sarosh-Madara
Copy link

Is it works fine in ScrollView?

@Shrikant-B
Copy link

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

@ashokbg
Copy link

ashokbg commented Mar 17, 2017

please can you explain by using ArrayList as dataresource ..

@shagung-optimus
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
Copy link

For dynamic make we should use recursion...

@talhahasanzia
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
Copy link

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

@MeMurillo
Copy link

Muchas gracias!

@carlosismael4
Copy link

carlosismael4 commented Aug 29, 2017

Thank u so much!! lml

@tribitinfotech
Copy link

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
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...

@dhavalpatel349
Copy link

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
Copy link

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

@tabetuba
Copy link

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

@vikasrajput007
Copy link

its a hundreds dollar code

@bereket-kassahun
Copy link

nice code, thanks.

@muhammadumair4533
Copy link

can yuo help ma to three level expandable list view inside drawer layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment