
This tutorial shows how to display a HashMap with String and ArrayList<String> as key value pairs, in an ExpandableListView.
Step 1: Create a new project with name ExpandableListView and package name com.myexample.listview. Select File/New/New Project. Fill the forms and click “Finish” button.
Step 2: Open res/layout/xml (or) main.xml and add following code. Here we add an ExpandableListView mainListview1.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ExpandableListView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/mainListview1"/>
</LinearLayout>
Step 4: In res/layout/ directory add a new file header_item.xml and add following code. Here we add a TextView for displaying the headers of lists.
<?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="wrap_content" android:orientation="horizontal" android:background="#990048"> <TextView android:layout_height="wrap_content" android:layout_width="match_parent" android:text="Large Text" android:id="@+id/listitemTextView1" android:padding="8dp" android:textSize="16sp" android:textColor="#FCFCFC" android:textStyle="bold"/> </LinearLayout>
Step 4: In res/layout/ directory add another file child_item.xml and add following code. Here we add a TextView for displaying the children in each list.
<?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="wrap_content" android:orientation="vertical" android:padding="10dp"> <TextView android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:layout_width="match_parent" android:text="Medium Text" android:textColor="#C00B00" android:id="@+id/childitemTextView1"/> </LinearLayout>
Step 5: Open app/src/main/java/package and open MainActivity.java. Add following code in it.
package com.myexample.listview;
import android.app.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import java.util.*;
import android.content.*;
public class MainActivity extends Activity {
private ExpandableListView listview1;
// Create a HashMap for all groups and their items
private HashMap<String, ArrayList<String>> allGroups = new HashMap<>();
// Create a list for all group headings
ArrayList<String> allheadings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listview1 = (ExpandableListView) findViewById(R.id.mainListview1);
// Toast item title when ListView item is clicked
listview1.setOnChildClickListener(new ExpandableListView.OnChildClickListener(){
@Override
public boolean onChildClick(ExpandableListView listview, View child, int groupposition, int childposition, long position){
Toast.makeText(getApplicationContext(), allGroups.get(allheadings.get(groupposition)).get(childposition), Toast.LENGTH_LONG).show();
return true;
}
});
// Create a separate list for each group, and add items to them
ArrayList<String> group1items = new ArrayList<>();
group1items.add("Group 1 item 1");
group1items.add("Group 1 item 2");
group1items.add("Group 1 item 3");
group1items.add("Group 1 item 4");
group1items.add("Group 1 item 5");
ArrayList<String> group2items = new ArrayList<>();
group2items.add("Group 2 item 1");
group2items.add("Group 2 item 2");
group2items.add("Group 2 item 3");
group2items.add("Group 2 item 4");
ArrayList<String> group3items = new ArrayList<>();
group3items.add("Group 3 item 1");
group3items.add("Group 3 item 2");
group3items.add("Group 3 item 3");
group3items.add("Group 3 item 4");
group3items.add("Group 3 item 5");
ArrayList<String> group4items = new ArrayList<>();
group4items.add("Group 4 item 1");
group4items.add("Group 4 item 2");
group4items.add("Group 4 item 3");
// put the lists created above in the HashMap allGroups, with separate keys
allGroups.put("This is Group 1", group1items);
allGroups.put("This is Group 2", group2items);
allGroups.put("This is Group 3", group3items);
allGroups.put("This is Group 4", group4items);
// Add all keys in HashMap allGroups to List String allheadings
allheadings = new ArrayList<String>(allGroups.keySet());
// Create a new CustomListAdapter and set it as adapter of ExpandableListView
CustomListAdapter adapter = new CustomListAdapter(this, allGroups, allheadings);
listview1.setAdapter(adapter);
((BaseAdapter)listview1.getAdapter()).notifyDataSetChanged();
}
public class CustomListAdapter extends BaseExpandableListAdapter {
private Context context;
HashMap<String, ArrayList<String>> groups;
ArrayList<String> headings;
// Public constructor
public CustomListAdapter(Context context, HashMap<String, ArrayList<String>> groups, ArrayList<String> headings) {
this.context = context;
this.groups = groups;
this.headings = headings;
}
@Override
public int getGroupCount() {
// Return total number of groups
return headings.size();
}
@Override
public int getChildrenCount(int position) {
// Return total items in each group
return groups.get(headings.get(position)).size();
}
@Override
public Object getGroup(int position) {
// Return group heading
return headings.get(position);
}
@Override
public Object getChild(int groupposition, int childposition) {
// Return child from specified group at the specified position
return groups.get(headings.get(groupposition)).get(childposition);
}
@Override
public long getGroupId(int position) {
return position;
}
@Override
public long getChildId(int groupposition, int childposition) {
return childposition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent){
View v = convertView;
// Inflate the layout for each list row
LayoutInflater _inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (v == null) {
v = _inflater.inflate(R.layout.header_item, null);
}
// Set Width of ListView to MATCH_PARENT
parent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// Get the TextView from CustomView for displaying group headings
TextView txtview = (TextView) v.findViewById(R.id.listitemTextView1);
// Set the text and image for current item using data from map list
txtview.setText(headings.get(groupPosition));
// Return the view for the current row
return v;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent){
View v = convertView;
// Inflate the layout for each list row
LayoutInflater _inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (v == null) {
v = _inflater.inflate(R.layout.child_item, null);
}
// Set Width of ListView to MATCH_PARENT
parent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// Get the TextView from CustomView for displaying children
TextView txtview = (TextView) v.findViewById(R.id.childitemTextView1);
// Set the text for current item using data from map list
txtview.setText((groups.get(headings.get(groupPosition))).get(childPosition));
// Return the view for the current row
return v;
}
@Override
public boolean isChildSelectable(int groupposition, int childposition)
{
return true;
}
}
}
Output:
Now run the app. The app will display a ExpandableListView.