BaseExpandableListAdapter in Android with Example - GeeksforGeeks

10 Nov, 2020
In many android apps, the developer may need to show multi-data for huge main data items. i.e. as per our example, under “Programming languages”, we need to show “Python”, “Java” etc., and under “Relational database” we need to show “Oracle”, “MySQL’ etc., For that purpose, we can use “BaseExpandableListAdapter“. It is a bridge between the UI component and the data source which fills data in the UI component. It holds the data and then sends the data to the Adapter view then the view can take the data from the Adapter view and shows the data on different views like ExpandableListView. It will provide access to the data of the children (categorized by groups), and also instantiate views for the children and groups. A sample GIF is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language. 
Let us see via code. Here is the code snippet for the CustomizedAdapter.java file:
Java
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseExpandableListAdapter;import android.widget.TextView;import java.util.ArrayList;  public class CustomizedAdapter extends BaseExpandableListAdapter {      private Context context;    private ArrayList<GroupInformation> mainSetName;      public CustomizedAdapter(Context context, ArrayList<GroupInformation> deptList) {        this.context = context;        this.mainSetName = deptList;    }      @Override    public Object getChild(int groupPosition, int childPosition) {        ArrayList<ChildInfo> productList = mainSetName.get(groupPosition).getSubsetName();        return productList.get(childPosition);    }      @Override    public long getChildId(int groupPosition, int childPosition) {        return childPosition;    }      @Override    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,                             View view, ViewGroup parent) {          ChildInfo detailInfo = (ChildInfo) getChild(groupPosition, childPosition);        if (view == null) {            LayoutInflater infalInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);            view = infalInflater.inflate(R.layout.child_items, null);        }        TextView childItem = (TextView) view.findViewById(R.id.childItm);        childItem.setText(detailInfo.getName().trim());          return view;    }      @Override    public int getChildrenCount(int groupPosition) {          ArrayList<ChildInfo> productList = mainSetName.get(groupPosition).getSubsetName();        return productList.size();      }      @Override    public Object getGroup(int groupPosition) {        return mainSetName.get(groupPosition);    }      @Override    public int getGroupCount() {        return mainSetName.size();    }      @Override    public long getGroupId(int groupPosition) {        return groupPosition;    }      @Override    public View getGroupView(int groupPosition, boolean isLastChild, View view,                             ViewGroup parent) {          GroupInformation headerInfo = (GroupInformation) getGroup(groupPosition);        if (view == null) {            LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);            view = inf.inflate(R.layout.group_items, null);        }          TextView heading = (TextView) view.findViewById(R.id.data);        heading.setText(headerInfo.getName().trim());          return view;    }      @Override    public boolean hasStableIds() {        return true;    }      @Override    public boolean isChildSelectable(int groupPosition, int childPosition) {        return true;    }  }
Check out the methods getChildView() and getGroupView(). They are used to create the View corresponding to the layout.
Method 1: 
getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
Explanation: Used to create a child View means a child item for a parent or group
Parameters:
groupPosition: Position for the parent(group) of the current child. The function returns an integer type value. Eg: Programming_Languages
childPosition: Position for current child item of the parent.
isLastChild: It returns either true/false for the current child item is the last child within its group.
convertView: It returns View which is used to set the layout for child items.
Parent: Set the view for the parent or group item.  The eventual parent of this new View.
Method 2: 
View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
Explanation: Used  to create our group or parent View
Parameters:
groupPosition: It tells the position of the parent or group of the child. The return type is an integer.
isExpanded: To indicate whether the group expanded and if so returns true or otherwise false.
convertView: Returns View which is used to set the layout for group items.
Parent: Used to set the view for the parent or group item.  The eventual parent of this new View.
Method 3: 
getChild(int groupPosition, int childPosition)
Explanation: Gets the data associated with the given child within the given group.
Parameters:
groupPosition: It tells the position for the parent or group of the child and returns an integer type value.
childPosition: It tells the position for the child of the given group and returns an integer type value.
Method 4:
getGroup(int groupPosition)
Explanation: Gets the data associated with the given group.
Parameters:
groupPosition: It tells the position for the parent or group of the child and returns an integer type value.
Method 5:
getChildrenCount(int groupPosition)
Explanation: Gets the number of children in a specified group.
Parameters:
groupPosition: It tells the position for the parent or group of the child and by using that position we calculate the number of children in that group.
Method 6:
getGroupCount()
Explanation: Get the total number of groups.
Method  7:
getGroupId(int groupPosition)
Explanation: Get the ID for the group at the given position.
Parameters:
groupPosition: It tells the position for the parent or group of the child and by using that position we get the ID for the group.
Method  8:
getChildId(int groupPosition, int childPosition)
Explanation: To get the ID for the given child within the given group.
Parameters:
groupPosition: It tells the position for the parent or group of the child and returns an integer type value.
childPosition: It tells the position for the child of the given group and returns an integer type value.
Method 9: 
isChildSelectable(int groupPosition, int childPosition)
Explanation: Checks whether the child at the specified position is selectable or not and returns a Boolean value
Parameters:
groupPosition: It tells the position for the parent or group of the child and returns an integer type value.
childPosition: It tells the position for the child of the given group and returns an integer type value.and by using that value we check whether the child is selectable or not.
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.
Step 2: Working with the activity_main.xml file
Go to the activity_main.xml file and refer to the following code. Below is the code for the activity_main.xml file.
XML
<?xml version="1.0" encoding="UTF-8"?><RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#fff"    android:orientation="vertical">      <ExpandableListView        android:id="@+id/simpleExpandableListView1"        android:layout_width="match_parent"        android:layout_height="fill_parent"        android:divider="#0f0"        android:dividerHeight="2dp" />  </RelativeLayout>
Step 3: Create new XML files
Go to the app > res > layout > right-click > New > Layout Resource File and name the file as child_items. Below is the code for the child_items.xml file. Here TextView is used for a subset of items Eg: Python.
XML
<?xml version="1.0" encoding="utf-8"?><RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@color/colorAccent"    android:orientation="vertical">      <TextView        android:id="@+id/childItm"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_marginLeft="15dp"        android:textAppearance="?android:attr/textAppearanceMedium" />  </RelativeLayout>
Similarly, create another layout resource file and name the file as group_items. Below is the code for the group_items.xml file. Here TextView is used for the main set of items Eg: Programming_Languages
XML
<?xml version="1.0" encoding="utf-8"?><LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="55dip"    android:orientation="vertical">      <TextView        android:id="@+id/data"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:paddingLeft="35sp"        android:textAppearance="?android:attr/textAppearanceLarge"        android:textStyle="bold" />  </LinearLayout>
Step 4: Create new Java files
Go to the app > java > your package name > right-click > New > Java Classe and name the file as ChildInfo. Below is the code for the ChildInfo.java file.
Java
public class ChildInfo {    private String name = "";          // Getter , setter methods    public String getName() {        return name;    }      public void setName(String name) {        this.name = name;    }}
Similarly, create another java class file and name the file as CustomizedAdapter. We have discussed this in the beginning section and also each overridden method. So you may copy the same code and implement it in the project.
Now create another java file and name the file as GroupInformation. Below is the code for the GroupInformation.java file.
Java
import java.util.ArrayList;  public class GroupInformation {      private String mainSetName;    private ArrayList<ChildInfo> list = new ArrayList<ChildInfo>();      public String getName() {        return mainSetName;    }      public void setName(String mainSetName) {        this.mainSetName = mainSetName;    }      public ArrayList<ChildInfo> getSubsetName() {        return list;    }      public void setSubsetName(ArrayList<ChildInfo> subSetName) {        this.list = subSetName;    }  }
Step 5: Working with the MainActivity.java file
Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.
Java
import android.os.Bundle;import android.view.View;import android.widget.ExpandableListView;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import java.util.ArrayList;import java.util.LinkedHashMap;  public class MainActivity extends AppCompatActivity {      private LinkedHashMap<String, GroupInformation> mainSet = new LinkedHashMap<String, GroupInformation>();    private ArrayList<GroupInformation> subSet = new ArrayList<GroupInformation>();      private CustomizedAdapter listAdapter;    private ExpandableListView simpleExpandableListView1;      @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);          // add data for displaying in expandable list view        loadData();          // get reference of the ExpandableListView from activity_main        simpleExpandableListView1 = (ExpandableListView) findViewById(R.id.simpleExpandableListView1);                  // create the adapter and by passing your ArrayList data        listAdapter = new CustomizedAdapter(MainActivity.this, subSet);        simpleExpandableListView1.setAdapter(listAdapter);          // setOnChildClickListener listener for child row click, so that we can get the value        simpleExpandableListView1.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {            @Override            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {                // get the group header                GroupInformation headerInfo = subSet.get(groupPosition);                // get the child info                ChildInfo detailInfo = headerInfo.getSubsetName().get(childPosition);                // display it or do something with it                Toast.makeText(getBaseContext(), headerInfo.getName() + "/" + detailInfo.getName(), Toast.LENGTH_LONG).show();                return false;            }        });                  // setOnGroupClickListener listener for group heading click        simpleExpandableListView1.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {            @Override            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {                // get the group header                GroupInformation headerInfo = subSet.get(groupPosition);                // display it or do something with it                Toast.makeText(getBaseContext(), headerInfo.getName(), Toast.LENGTH_LONG).show();                return false;            }        });    }      // load some initial data into out list    private void loadData() {          addDetails("Programming_Languages", "Python");        addDetails("Programming_Languages", "Java");        addDetails("Programming_Languages", "Kotlin");        addDetails("Programming_Languages", "NodeJS");        addDetails("Programming_Languages", "GO");          addDetails("Relational_Database", "Oracle");        addDetails("Relational_Database", "SQLServer");        addDetails("Relational_Database", "MySQL");          addDetails("NoSQL_Database", "MongoDB");        addDetails("NoSQL_Database", "Cassandra");        addDetails("NoSQL_Database", "CouchDB");      }          // here we maintain main set like Programming languages and subsets like Python    private int addDetails(String mainSet, String subSet) {          int groupPosition = 0;          // check the hash map if the group already exists        GroupInformation headerInfo = this.mainSet.get(mainSet);                  // add the group if doesn't exists        if (headerInfo == null) {            headerInfo = new GroupInformation();            headerInfo.setName(mainSet);            this.mainSet.put(mainSet, headerInfo);            this.subSet.add(headerInfo);        }          // get the children for the group        ArrayList<ChildInfo> subList = headerInfo.getSubsetName();                  // size of the children list        int listSize = subList.size();                  // add to the counter        listSize++;          // create a new child and add that to the group        ChildInfo detailInfo = new ChildInfo();        detailInfo.setName(subSet);        subList.add(detailInfo);        headerInfo.setSubsetName(subList);          // find the group position inside the list        groupPosition = this.subSet.indexOf(headerInfo);        return groupPosition;    }}
On running the app, on the emulator, we can able to view the output as attached in the video. This feature is a much-required feature across many apps.
android
Technical Scripter 2020
Android
Java
Technical Scripter
Java
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
How to Create and Add Data to SQLite Database in Android?
Services in Android with Example
Broadcast Receiver in Android With Example
Content Providers in Android with Example
Android RecyclerView in Kotlin
Arrays in Java
Split() String method in Java with examples
For-each loop in Java
Arrays.sort() in Java with examples
Initialize an ArrayList in Java