Android Expandable ListView Tutorial: Building Collapsible Lists

Android Expandable Listview :

Android Expandable Listview name itself says that it will be expanded depending upon categories.

Generally when we deal with menu’s which are to be show in listview, Sometimes we need to show sub-categories so for this purpose we will deal with.

In almost every app expandable listview in android, where there is a category there we can find these expandable listview, like new apps TOI, Hindu, swiggy, zomato and many other food delivery apps use these kinds of list’s to make the user interface much better.

Almost these list can be dynamically populated from json array’s a lot of information can be stored and populated on demand making the efficient use of screen space available and avoiding inconvenience.

Android Expandable Listview is the finest way to publish data to the users i.e., in categorical way such that it it easy to understand and represent too with the help of this blog.

Categories are shown as group headers and sub categories are shown as child items in expandable listview.

 

expandablelistview1

I have shown a Android Expandable Listview example which contains three categories

  1. Sports
  2. Colors
  3. Animals

Which are further sub categorized for example:

expandablelistview2

 

Android Expandable Listview Code :

 

Creating android ExpandableListviewAdapter File for Android Expandable Listview

ExpandableListAdapter.java :

Here we use a traditional way to bind the views you may use databinding too.

In this Adapter we are fully concentrating on child view populating data and onClickListener’s as we have considered group’s Click listeners in MainActivity.

public class ExpandableListAdapter extends BaseExpandableListAdapter {

    private Context context;
    private List<String> ParentItem;
    private HashMap<String, List<String>> ChildItem;


    public ExpandableListAdapter(Context context, List<String> ParentItem,
                                 HashMap<String, List<String>> ChildItem) {
        this.context = context;
        this.ParentItem = ParentItem;
        this.ChildItem = ChildItem;
    }

    @Override
    public Object getChild(int listPosition, int expandedListPosition) {
        return this.ChildItem.get(this.ParentItem.get(listPosition))
                .get(expandedListPosition);
    }

    @Override
    public long getChildId(int listPosition, int expandedListPosition) {
        return expandedListPosition;
    }

    @Override
    public View getChildView(int listPosition, final int expandedListPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        final String expandedListText = (String) getChild(listPosition, expandedListPosition);
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) this.context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.child_item, null);
        }
        TextView text1 = (TextView) convertView.findViewById(R.id.item1);
        TextView text2 = (TextView) convertView.findViewById(R.id.item2);
        text1.setText(""+expandedListPosition);
        text2.setText(""+expandedListText);
        return convertView;
    }

    @Override
    public int getChildrenCount(int listPosition) {
        return this.ChildItem.get(this.ParentItem.get(listPosition))
                .size();
    }

    @Override
    public Object getGroup(int listPosition) {
        return this.ParentItem.get(listPosition);
    }

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

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

    @Override
    public View getGroupView(int listPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        String listTitle = (String) getGroup(listPosition);
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) this.context.
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.parent_item, null);
        }
        TextView listTitleTextView = (TextView) convertView
                .findViewById(R.id.listTitle);
        listTitleTextView.setTypeface(null, Typeface.BOLD);
        listTitleTextView.setText(listTitle);
        return convertView;
    }

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

    @Override
    public boolean isChildSelectable(int listPosition, int expandedListPosition) {
        return true;
    }


    public static HashMap<String, List<String>> getData() {
        HashMap<String, List<String>> ParentItem = new HashMap<String, List<String>>();

        List<String> Colors = new ArrayList<String>();
        Colors.add("Red");
        Colors.add("Green");
        Colors.add("Blue");
        Colors.add("Maroon");
        Colors.add("Yellow");
        Colors.add("Violet");
        Colors.add("Pink");

        List<String> Animals = new ArrayList<String>();
        Animals.add("Lion");
        Animals.add("Tiger");
        Animals.add("Leopard");
        Animals.add("Cheetah");
        Animals.add("Bear");

        List<String> Sports = new ArrayList<String>();
        Sports.add("Cricket");
        Sports.add("Football");
        Sports.add("Tennis");
        Sports.add("Basket Ball");
        Sports.add("Base Ball");


        ParentItem.put("Colors", Colors);
        ParentItem.put("Animals", Animals);
        ParentItem.put("Sports", Sports);

        return ParentItem;



    }
}

 

Assigning expandableListView set onClickListener for group click and child click.

MainActivity.java :

We need to take care of Group click listener and then after the group expansion we need to make sure of the child click listeners too.

 

 

public class MainActivity extends Activity {

    ExpandableListView expandableListView;
    ExpandableListAdapter expandableListAdapter;
    List<String> expandableListTitle;
    HashMap<String, List<String>> expandableListDetail;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        expandableListView = (ExpandableListView) findViewById(R.id.expandableListView);
        expandableListDetail = ExpandableListAdapter.getData();
        expandableListTitle = new ArrayList<String>(expandableListDetail.keySet());
        expandableListAdapter = new ExpandableListAdapter(this, expandableListTitle, expandableListDetail);
        expandableListView.setAdapter(expandableListAdapter);
        expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() {

            @Override
            public void onGroupExpand(int groupPosition) {
                Toast.makeText(getApplicationContext(),
                        expandableListTitle.get(groupPosition) + " ListView Open.",
                        Toast.LENGTH_SHORT).show();
            }
        });

        expandableListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {

            @Override
            public void onGroupCollapse(int groupPosition) {
                Toast.makeText(getApplicationContext(),
                        expandableListTitle.get(groupPosition) + " ListView Closed.",
                        Toast.LENGTH_SHORT).show();

            }
        });

        expandableListView.setOnChildClickListener(new OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v,
                                        int groupPosition, int childPosition, long id) {
                Toast.makeText(getApplicationContext(),
                        expandableListDetail.get(
                                expandableListTitle.get(groupPosition)).get(
                                childPosition), Toast.LENGTH_SHORT
                )
                        .show();
                return false;
            }
        });
    }
}

 

activity_main.xml :

Adding ExpandableListView to  activity_main.xml.

Here we are making use of a ExpandableListView to make sure our list data is loaded with expansion and compression 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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin">

    <ExpandableListView
        android:id="@+id/expandableListView"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:indicatorLeft="?android:attr/expandableListPreferredItemIndicatorLeft"
        android:divider="#A4C739"
        android:dividerHeight="1dp" />

</RelativeLayout>

 

 

Adding parent (Group Header).

 

parent_item.xml :

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/listTitle"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft"
        android:textColor="#ffffff"
        android:background="#B40404"
        android:paddingTop="10dp"
        android:paddingBottom="10dp" />
</LinearLayout>

 

Adding child_item to listview

child_item.xml :

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="2"
        android:padding="2dp">

    <TextView
        android:id="@+id/item1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
        android:paddingTop="10dp"
        android:layout_weight="1.5"
        android:paddingBottom="10dp" />


    <TextView
        android:id="@+id/item2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
        android:paddingTop="10dp"
        android:layout_weight="0.5"
        android:paddingBottom="10dp" />

    </LinearLayout>
</LinearLayout>

 

 

Android Expandable Listview Output :

Here finally we can see the output of Expandable Listview example.

Android Expandable Listview example

Group and Child On Click Toast

 

Android Expandable Listview example Android Expandable Listview example

Android Expandable Listview example Android Expandable Listview example

Android Expandable Listview example Android Expandable Listview example

 

If you have any query’s in this tutorial on Expandable Listview comment below and for more on listview’s may refer

Like and share this tutorial for more interesting updates.

Show Buttons
Hide Buttons
Read previous post:
Step-by-Step Tutorial: Implementing Android Push Notifications

  Android push notification : In this android development tutorial we will deal with android push notification if you are new to this...

Close