How to create an expandable listview in Fragments in Android Studio?

Please Share On:

Android ExpandableListView is a view that shows an item in a vertically scrolling two-level list. It is expanding and collapses whenever the user touches on a group item. The top-level list is group items and second-level items are their respective child items.

In the previous tutorial, I show you how to create an expandable listview in android activity. Here, I am going to show you how to display expandable listview in fragments.

Files need to create:

You have to create 5 XML files and 5 java classes as below:

  1. Design your activity_main.xml file
  2. Create fragment layout named fragment_tab1.xml
  3. Create another fragment layout named fragment_tab2.xml.
  4. Create header items layout file and name as list_group.xml
  5. Create a Child items layout file and name as list_item.xml
  6. Create a Custom Expandable ListView Adapter in the Java class and name as expandableListAdapter.java
  7. Create java classes for your Fragment layout and name Fragment_tab1.java
  8. Another fragment java class is named Fragment_tab2.java.
  9. Add some code in your MainActivity.java
  10. Create TapPagerAdapter.java class for page slide

Here is a screenshot how what your above files look like after being created.

Now let’s start the above steps from 1 to 10.

1) Create activity_main.xml

Design your activity_main.xml file and put TabLayout and ViewPager here. Add the below code in your activity_main.xml.

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/blue"
            app:tabSelectedTextColor="@color/white"
            app:tabTextColor="@color/white"
            tools:ignore="SpeakableTextPresentCheck" />
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:ignore="SpeakableTextPresentCheck" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

2) Create fragment_tab1.xml

Create another XML file for the fragment to display expandable listview and name as fragment_tab1 .xml and add the following code inside it.

<?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/expListView"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:divider="@android:color/holo_blue_dark"
        android:dividerHeight="1dp">
    </ExpandableListView>
</RelativeLayout>

3) Create fragment_tab2.xml

Create another XML file for the fragment to display expandable listview and name as fragment_tab2 .xml and add the following code inside it.

<?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/expListView"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:divider="@android:color/holo_blue_dark"
        android:dividerHeight="1dp">
    </ExpandableListView>
</RelativeLayout>

4) Create list_group.xml

Create another XML file for your group header titles and name as list_group.xml and add the following code inside it.

Here is a full code of my CustomExpandableListViewAdapter.java class

<?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:orientation="vertical">


    <TextView
        android:id="@+id/header_title"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:gravity="center"
        android:background="@color/background"/>

</RelativeLayout>

5) Create list_item.xml

Create another child layout for child items and name as list_item.xml. Design your child’s layout as you like. Here is a sample of my  list_item .xml layout.

<?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">

    <TextView
        android:id="@+id/text_child"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_marginStart="50dp"
        android:gravity="center_vertical"
        android:text="TextView"
        android:textSize="18sp" />
</RelativeLayout>

6) Create ExpandableListAdapter.java

Create your custom expandable listview adapter and name it as ExpandableListAdapter.java and extends this adapter from BaseExpandableListAdapter.

Here is a full code of my  ExpandableListAdapter .java class

package com.elsebazaar.expandablelistviewexample;

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;

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.list_item, null);
        }
        TextView txtListChild = (TextView) convertView.findViewById(R.id.text_child);
        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.list_group, null);
        }
        TextView lblListHeader = (TextView) convertView
                .findViewById(R.id.header_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;
    }
}

7) Fragment_tab1.java

package com.elsebazaar.expandablelistviewexample;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.ExpandableListView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

public class Fragment_tab1 extends Fragment {
    private Context context;
    private ExpandableListView expListView;
    ExpandableListAdapter listAdapter;

    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_tab1, container, false);

    }
    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        expListView = (ExpandableListView) view.findViewById(R.id.expListView);

        createListData();

        // Expandable Listview on group click listerner
        expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v,
                                        int groupPosition, long id) {
                // TODO GroupClickListener work
                return false;
            }
        });

        // Expandable Listview Group Expanded Listener
        expListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
            @Override
            public void onGroupExpand(int groupPosition) {
                // TODO GroupExpandListener work
            }
        });

        // Expandable Listview Group Collapsed listener
        expListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
            @Override
            public void onGroupCollapse(int groupPosition) {
                // TODO GroupCollapseListener work
            }
        });

        // Expandable Listview on child click listener
        expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v,
                                        int groupPosition, int childPosition, long id) {
                Toast.makeText( context,
                        "Awesome, I clicked:  "+ Objects.requireNonNull(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("Fruits");
        listDataParent.add("Vegetables");
        listDataParent.add("Meats");
        listDataParent.add("Drinks");

        // Adding child data
        List<String> Fruits = new ArrayList<String>();
        Fruits.add("Apples");
        Fruits.add("Bananas");
        Fruits.add("Mangoes");
        Fruits.add("Pineapples");
        Fruits.add("Watermelon");
        Fruits.add("Dragon Fruits");
        Fruits.add("Kiwi");

        List<String> Vegetables = new ArrayList<String>();
        Vegetables.add("Cabbage");
        Vegetables.add("Brussels Sprouts");
        Vegetables.add("Carrots");
        Vegetables.add("Collard Greens");
        Vegetables.add("Eggplant");
        Vegetables.add("Cauliflower");

        List<String> Meats = new ArrayList<String>();
        Meats.add("Beef");
        Meats.add("Lamb");
        Meats.add("Veal");
        Meats.add("Pork");
        Meats.add("Kangaroo");

        List<String> Drinks = new ArrayList<String>();
        Drinks.add("Coca Cola");
        Drinks.add("Fanta");
        Drinks.add("Sprite");
        Drinks.add("Soda");
        Drinks.add("Lemonade");

        listDataChild.put(listDataParent.get(0), Fruits); // Header, Child data
        listDataChild.put(listDataParent.get(1), Vegetables);
        listDataChild.put(listDataParent.get(2), Meats);
        listDataChild.put(listDataParent.get(3), Drinks);


        listAdapter = new ExpandableListAdapter(context, listDataParent, listDataChild);
        expListView.setAdapter(listAdapter);
    }
}

8) Fragment_tab2.java

package com.elsebazaar.expandablelistviewexample;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Fragment_tab2 extends Fragment {
    private Context context;
    private ExpandableListView expListView;
    ExpandableListAdapter listAdapter;

    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_tab1, container, false);

    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        expListView = (ExpandableListView) view.findViewById(R.id.expListView);

        createListData();

        // Listview Group click listener
        expListView.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
        expListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
            @Override
            public void onGroupExpand(int groupPosition) {
                // TODO GroupExpandListener work
            }
        });

        // Listview Group collasped listener
        expListView.setOnGroupCollapseListener(new ExpandableListView.OnGroupCollapseListener() {
            @Override
            public void onGroupCollapse(int groupPosition) {
                // TODO GroupCollapseListener work
            }
        });

        // Listview on child click listener
        expListView.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("Vegetables");
        listDataParent.add("Drinks");
        listDataParent.add("Fruits");
        listDataParent.add("Meats");


        List<String> Vegetables = new ArrayList<String>();
        Vegetables.add("Cabbage");
        Vegetables.add("Brussels Sprouts");
        Vegetables.add("Carrots");
        Vegetables.add("Collard Greens");
        Vegetables.add("Eggplant");
        Vegetables.add("Cauliflower");


        List<String> Drinks = new ArrayList<String>();
        Drinks.add("Coca Cola");
        Drinks.add("Fanta");
        Drinks.add("Sprite");
        Drinks.add("Soda");
        Drinks.add("Lemonade");

        // Adding child data
        List<String> Fruits = new ArrayList<String>();
        Fruits.add("Apples");
        Fruits.add("Bananas");
        Fruits.add("Mangoes");
        Fruits.add("Pineapples");
        Fruits.add("Watermelon");
        Fruits.add("Dragon Fruits");
        Fruits.add("Kiwi");

        List<String> Meats = new ArrayList<String>();
        Meats.add("Beef");
        Meats.add("Lamb");
        Meats.add("Veal");
        Meats.add("Pork");
        Meats.add("Kangaroo");

        listDataChild.put(listDataParent.get(0), Vegetables);
        listDataChild.put(listDataParent.get(1), Drinks);
        listDataChild.put(listDataParent.get(2), Fruits); // Header, Child data
        listDataChild.put(listDataParent.get(3), Meats);


        listAdapter = new ExpandableListAdapter(context, listDataParent, listDataChild);
        expListView.setAdapter(listAdapter);
    }
}

9) Create MainActivity.java

package com.elsebazaar.expandablelistviewexample;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.ViewPager;

import android.os.Bundle;

import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Toolbar toolbar;
        TabPagerAdapter adapter;

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
        adapter = new TabPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.setupWithViewPager(viewPager);

    }
}

10) Create TapPagerAdapter.java

package com.elsebazaar.expandablelistviewexample;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

public class TabPagerAdapter extends FragmentPagerAdapter {
    public TabPagerAdapter(FragmentManager fm) {
        super(fm);
    }
    @NonNull
    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;
        switch (position) {
            case 0:
                return new Fragment_tab1();
            case 1:
                return new Fragment_tab2();
            default:
                assert false;
                return fragment;
        }
    }
    @Override
    public int getCount() {
        return 2;
    }
    @Override
    public CharSequence getPageTitle(int position) {
        String title = null;
        if (position == 0)
        {
            title = "List";
        }
       else if (position == 1)
        {
            title = "Second List";
        }
        return title;
    }
}

Now run your program. You should get the results as before.

Output:



You may be interested in the following topics:

Leave a Reply

Your email address will not be published. Required fields are marked *

Copyright @2023. All Right Reserved.


Social media & sharing icons powered by UltimatelySocial