How to implement an Expandable ListView in Android

Expandable Listview

Expandable ListView is a type of view very much similar to a  List view.This view shows items in a vertically scrolling two-level list.This has two levels – group and children, which differs it from the List view.Group individually be expanded to show its children.Basically items are grouped inside the list much like giving a category heading to a bunch of similar items and then group them by the category headings.We can easily listen for OnClick events on the group or the individual children by attaching listener to the Expandable ListView. Below are the steps described to implement Expandable ListView:

Steps to implement Expandable ListView in Android:

1) Create  xml layout files

We need to create three xml layout files – one for main activity layout, second for header (group) and the third one for child layout.

main.xml for MainActivity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:background="@color/white"
    android:layout_height="match_parent"
    android:layout_marginTop="@dimen/tool_bar_height"
    android:orientation="vertical"
    >

    <ExpandableListView
        android:id="@+id/forumList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
    </ExpandableListView>

</LinearLayout>

header.xml for Header Layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dp"
    android:background="@color/backGroundColor">

   <!-- <ImageView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:background="@drawable/icon_drop"
        android:layout_margin="10dp"/>-->


    <TextView
        android:id="@+id/lblListHeader"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="30dp"
        android:textSize="21dp"
        android:textColor="@color/themeDarkColor"
        android:text="Header"/>

</LinearLayout>

child.xml for Child Layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/FrameStyle"
    android:layout_marginTop="0dp"
    android:layout_marginBottom="3dp"
    >
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:padding="10dp"
        android:id="@+id/count_layout">
        <TextView
            android:id="@+id/count"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18dp"
            android:gravity="center_vertical"
            android:padding="5dp"
            android:text="2"

            />
        <TextView
            android:id="@+id/view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="15dp"
            android:gravity="center_horizontal"
            android:layout_below="@+id/count"
            android:text="view"
            />
    </RelativeLayout>
    <TextView
        android:id="@+id/title"
        style="@style/CellHighlightTitleStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:padding="10dp"
        android:paddingLeft="20dp"
        android:layout_toRightOf="@+id/count_layout"
        android:text="Topic"
        />


</RelativeLayout>

2) Add  elements to the Group and Child

In Main Activity add elements of the group and child to be displayed in list.

private void setValue(List<Forum> forums) {
        listDataHeader = new ArrayList<String>();
        listDataChild= new HashMap<String, List<Forum>>();
        String previous_header=null;
        for(int i=0;i<forums.size();i++){
             header=forums.get(i).getCategory();
            if(!header.equals(previous_header)){
                listDataHeader.add(forums.get(i).getCategory());
            }
            if(header.equals("General")){
                 generalList.add(forums.get(i));
            }else
                 offTopicList.add(forums.get(i));
            previous_header= header;
        }

        listDataChild.put(listDataHeader.get(0), generalList);
        listDataChild.put(listDataHeader.get(1), offTopicList);

3) Implement Adapter for Exapandable ListView

In this we have to implement the adapter.We are using custom adapter which extends  BaseExpandableListAdapter. This class provides required methods to render listview.

getGroupView() – Returns view for the list group header
getChildView() – Returns view for list child item.

public class ForumAdapter extends BaseExpandableListAdapter {
      private Context _context;
      private List<String> _listDataHeader; // header titles
      private HashMap<String, List<Forum>> _listDataChild; // header child
    public ForumAdapter(Context context, List<String> listDataHeader, HashMap<String,      List<Forum>> listDataChild) {
        //initialize the parameters
    }
    @Override
    public Object getChild(int groupPosition, int childPosititon) {

        //to get children of the respective header(group).
        return  this._listDataChild.get(this._listDataHeader.get(groupPosition))
                .get(childPosititon);
    }
    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    // set the child view with value
    @Override
    public View getChildView(int groupPosition, final int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        final Forum item = (Forum) getChild(groupPosition, childPosition);
        if (convertView == null) {
          convertView = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.child, parent, false);
        }
        TextView title = (TextView)convertView.findViewById(R.id.title);
        TextView post  = (TextView) convertView.findViewById(R.id.view);
        TextView count  = (TextView) convertView.findViewById(R.id.count);
         title.setText(item.getTitle());
         count.setText(item.getPostCount().toString());
         post.setText("Posts");
        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;
    }

    //set the header view with values
    @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.header, null);
        }
        TextView lblListHeader = (TextView)convertView.findViewById(R.id.lblListHeader);
        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;
    }
}

4) Modify the Main Activity

After that, set the Expandable ListView Adapter and  add listener to the child (If you want to do anything on child click).

  listAdapter = new ExpandableAdapter(getActivity(),listDataHeader, listDataChild);
        
        // setting list adapter
        expListView.setAdapter(listAdapter);
        expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,int childPos               ition, long id) {
            }
        });

That’s All..:-)

In Conclusion:

If you have implemented listview before then you will find it more easy to implement. Implementation of the Expandable ListView has very easy steps as described above.It gives more flexibility to the android user and make the UI more friendly and attractive.You can edit the view of child as well as group in your own way to make it more attractive as per your requirements.

Refrences:

ListView

Expandable ListView

How to implement an Expandable ListView in Android was last modified: September 6th, 2015 by Neha Prakash