
This is a wonderful example to show you, how to create an expandable list view in android. I have learned already in the previous article, how to create a list view in android by Recyclerview.
So now you can use the ExpandableListView component to create a list of parent and child relationship. This is an awesome component to convert your JSON/XML data to represent with a respective manner.
Methods of Expandable list view
Expandable List view in android loads the data into the items associated with this view. These are some important methods in this class:
- setChildIndicator(Drawable)
- setGroupIndicator(Drawable)
- getGroupView()
- getChildView()
setChildIndicator(Drawable): This is used to show an indicator beside each item representing the current state. If the child is the last child for a group, the state state_last will be set.
setGroupIndicator(Drawable): An indicator is drawn beside the group representing its state i.e. expanded or collapsed. If the group is empty. The state state_empty will be set. If the group is expanded, the state state_expanded will be set.
getGroupView(): It returns a view for the list group header.
getChildView(): It returns view for list child item.
The expandable view that shows items in a vertically scrolling two-level list. Expandable lists are able to show an indicator beside each item to display the item’s current state.
The states are usually one of an expanded group, collapsed group, child, or last child.

All pages of project
Create your main layout with the help of tab layout and toolbar options.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/layoutmain">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_search"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:tabGravity="center"
app:tabMode="scrollable"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_below="@+id/layoutmain" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayout"
android:layout_marginTop="60dp">
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
fragment_data_list.xml
<?xml version="1.0" encoding="utf-8"?>
<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">
<ExpandableListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:divider="@null">
</ExpandableListView>
</RelativeLayout>
In the adapter_list_group layout file – you can create your design. In this example, I have used the card view for the good looking header section.
adapter_list_group.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="25dp"
android:orientation="vertical">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="5dp"
card_view:cardUseCompatPadding="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_margin="5dp"
android:orientation="vertical">
<TextView
android:id="@+id/text_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginLeft="25dp"
android:gravity="center" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
adapter_list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="25dp"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="75dp"
android:layout_height="75dp"
app:srcCompat="@drawable/circle"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="25dp" />
<TextView
android:id="@+id/text_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginLeft="90dp"
android:text="TextView"
android:textSize="18sp" />
</RelativeLayout>
Handle all ClickListeners from your DataFragment.java class. Basically, four types of ClickListeners are there:
- ExpandableListView.OnChildClickListener
- ExpandableListView.OnGroupClickListener
- ExpandableListView.OnGroupCollapseListener
- ExpandableListView.OnGroupExpandListener
ExpandableListView.OnChildClickListener: You can handle ChildClickListener, This is overridden to implement the callback method that’s invoked when a child in the expanded list is clicked
ExpandableListView.OnGroupClickListener: This is overridden to implement the callback method that’s invoked when a group header in the expanded list is clicked.
ExpandableListView.OnGroupCollapseListener: This is used for notifying when a group is collapsed.
ExpandableListView.OnGroupExpandListener: This is used to notify when a group is expanded.
DataFragment.java
package com.legendblogs.expandablelistview;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by legendblogs on 21-01-2019.
*/
public class DataFragment extends Fragment {
private Context context;
private ExpandableListView list_view;
List<String> listDataParent;
HashMap<String, List<String>> listDataChild;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.context = this.getActivity();
return inflater.inflate(R.layout.fragment_data_list, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
list_view = (ExpandableListView) view.findViewById(R.id.list_view);
createListData();
// Listview Group click listener
list_view.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
// TODO GroupClickListener work
return false;
}
});
// Listview Group expanded listener
list_view.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
// TODO GroupExpandListener work
}
});
// Listview Group collasped listener
list_view.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
@Override
public void onGroupCollapse(int groupPosition) {
// TODO GroupCollapseListener work
}
});
// Listview on child click listener
list_view.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
Toast.makeText( context,
"wow, this is - "+listDataChild.get(listDataParent.get(groupPosition)).get(childPosition),
Toast.LENGTH_SHORT).show();
return false;
}
});
}
private void createListData() {
listDataParent = new ArrayList<String>();
listDataChild = new HashMap<String, List<String>>();
// Adding child data
listDataParent.add("Colors");
listDataParent.add("Fruits");
listDataParent.add("Animals");
// Adding child data List one
List<String> colors = new ArrayList<String>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");
colors.add("Yellow");
colors.add("Blue");
// Adding child data List two
List<String> fruits = new ArrayList<String>();
fruits.add("Apples");
fruits.add("Bananas");
fruits.add("Apricots");
fruits.add("Cherries");
fruits.add("Elderberry");
fruits.add("Dates");
// Adding child data List three
List<String> animals = new ArrayList<String>();
animals.add("Dog");
animals.add("Cat");
animals.add("Elephant");
animals.add("horse");
listDataChild.put(listDataParent.get(0), colors); // Header, Child data
listDataChild.put(listDataParent.get(1), fruits); // Header, Child data
listDataChild.put(listDataParent.get(2), animals); // Header, Child data
ExpandableListAdapter listAdapter = new ExpandableListAdapter(context, listDataParent, listDataChild);
list_view.setAdapter(listAdapter);
}
}
TabPagerAdapter.java
package com.legendblogs.expandablelistview;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
/**
* Created by legendblogs on 21-01-2019.
*/
public class TabPagerAdapter extends FragmentPagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position == 0)
{
fragment = new DataFragment();
}
return fragment;
}
@Override
public int getCount() {
return 1;
}
@Override
public CharSequence getPageTitle(int position) {
String title = null;
if (position == 0)
{
title = "List";
}
return title;
}
}
ExpandableListAdapter.java
package com.legendblogs.expandablelistview;
import android.content.Context;
import android.graphics.Typeface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.List;
/**
* Created by legendblogs on 21-01-2019.
*/
public class ExpandableListAdapter extends BaseExpandableListAdapter {
private Context _context;
private List<String> _listDataHeader; // header titles
// child data in format of header title, child title
private HashMap<String, List<String>> _listDataChild;
public ExpandableListAdapter(Context context, List<String> listDataHeader,
HashMap<String, List<String>> listChildData) {
this._context = context;
this._listDataHeader = listDataHeader;
this._listDataChild = listChildData;
}
@Override
public Object getChild(int groupPosition, int childPosititon) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.get(childPosititon);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final String childText = (String) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.adapter_list_item, null);
}
TextView txtListChild = (TextView) convertView
.findViewById(R.id.text_desc);
txtListChild.setText(childText);
return convertView;
}
@Override
public int getChildrenCount(int groupPosition) {
return this._listDataChild.get(this._listDataHeader.get(groupPosition))
.size();
}
@Override
public Object getGroup(int groupPosition) {
return this._listDataHeader.get(groupPosition);
}
@Override
public int getGroupCount() {
return this._listDataHeader.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater infalInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = infalInflater.inflate(R.layout.adapter_list_group, null);
}
TextView lblListHeader = (TextView) convertView
.findViewById(R.id.text_title);
lblListHeader.setTypeface(null, Typeface.BOLD);
lblListHeader.setText(headerTitle);
return convertView;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
MainActivity.java
package com.legendblogs.expandablelistview;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
/**
* Created by legendblogs on 21-01-2019.
*/
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabPagerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar_search);
if(getSupportActionBar() == null) {
setSupportActionBar(toolbar);
}else toolbar.setVisibility(View.GONE);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
adapter = new TabPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
}
In the Gradle file, you need to add one more line:
implementation 'com.android.support:design:28.0.0'
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.legendblogs.expandablelistview"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.legendblogs.expandablelistview">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Did you find this page helpful?
X