Android expandable listview header

Sometimes, you have to add header to an expandable list. For example, you have an expandable list that displays provinces and number of population living in the provinces. In each province, there are a lot of districts and population living in the district. To make it easy to understand your data presentation, you expandable list should have the header text as shown in the screen shot below:


expandablelistview header


Now to have an example application on adding header to expandable list, you create a new Android project. Then add an ExpandableListView to the activity_main.xml file.




<?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="match_parent"
   android:orientation="vertical"
>
   <ExpandableListView
     android:id="@+id/lvExp"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
     android:groupIndicator="@null"
     android:background="#f5f5f5"
       />

</LinearLayout>


In the res/layout directory, you create three more layout files: list_group.xml, list_member.xml, and list_header.xml. The list_group.xml defines layout for the groups of the expandable list. The list_member defines layout of every child or member. And the list_header defines layout of the list header. Each layout is row that has two fields. One field displays province or district name and another field display number of population.


list_group.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="wrap_content"
   android:orientation="horizontal"
   android:padding="8dp"
   android:background="#ffdbdbdb">


   <TextView
     android:id="@+id/txtprovince"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:textSize="17sp"
     android:textColor="#ff808021"
     android:layout_weight="1"
     />

   <TextView
     android:id="@+id/txtpnum"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:textSize="17sp"
     android:textColor="#ff808021"
     android:layout_weight="1"
       />
</LinearLayout>



list_member.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="wrap_content"
   android:orientation="horizontal"
   android:padding="8dp"
   android:background="#ffdbdbdb">


   <TextView
     android:id="@+id/txtdistrict"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
     android:textSize="15sp"
     android:layout_weight="1"
     />

   <TextView
     android:id="@+id/txtdnum"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:paddingLeft="?android:attr/expandableListPreferredChildPaddingLeft"
     android:textSize="15sp"
     android:layout_weight="1"
     />
</LinearLayout>


list_header.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="wrap_content"
   android:orientation="horizontal"
   android:padding="8dp"
   android:background="#135557">

   <TextView
     android:id="@+id/txtheadtext"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:textSize="15sp"
     android:layout_weight="1"
     android:textColor="#f8f8f8"
     android:text="Province"
     />

   <TextView
     android:id="@+id/txtheadnum"
     android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:textSize="15sp"
     android:layout_weight="1"
     android:textColor="#f8f8f8"
     android:text="Number of population"
     />
</LinearLayout>



In the src directory, you create two classes: PlaceNum and ExpandableListAdapter. An object of the PlaceNum class is used to store a pair of province or district name and number of population. The ExpandableListAdapter allows you to bind the ExpandableListView to the groups (province and number of population) and member data (districts and number of population).


PlaceNum class

public class PlaceNum {
   private String place;
   private long num;
   PlaceNum(String place, long num){
     this.place=place;
     this.num=num;
   }
   public void setPlace(String place){
     this.place=place;
   }
   public void setNum(long num){
     this.num=num;
   }
   public String getPlace(){
     return place;
   }
   public long getNum(){
     return num;
   }
}


ExpandableListAdapter class

import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.graphics.Typeface;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
public class ExpandableListAdapter extends BaseExpandableListAdapter {

   private Context _context;
   private List<PlaceNum> _listGroupTitle; // header titles
   private HashMap<String, List<PlaceNum>> _listDataMembers;

   public ExpandableListAdapter(Context context, List<PlaceNum> listGroupTitle,
                      HashMap<String, List<PlaceNum>> listDataMembers) {
     this._context = context;
     this._listGroupTitle = listGroupTitle;
     this._listDataMembers = listDataMembers;

   }

   @Override
   public Object getChild(int groupPosition, int childPosititon) {
     return this._listDataMembers.get(this._listGroupTitle.get(groupPosition).getPlace())
           .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) {

     PlaceNum memData=(PlaceNum)getChild(groupPosition, childPosition);
      if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_member, null);
     }

     TextView txtDisName= (TextView) convertView.findViewById(R.id.txtdistrict);
     txtDisName.setText(Html.fromHtml("<b>"+memData.getPlace()+"</b>"));
     TextView txtNum= (TextView) convertView.findViewById(R.id.txtdnum);
     txtNum.setText(Html.fromHtml("<b>"+memData.getNum()+"</b>"));
     return convertView;
   }

   @Override
   public int getChildrenCount(int groupPosition) {
     return this._listDataMembers.get(this._listGroupTitle.get(groupPosition).getPlace()).size();
   }

   @Override
   public Object getGroup(int groupPosition) {
     return this._listGroupTitle.get(groupPosition);
   }

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

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

   @Override
   public View getGroupView(int groupPosition, boolean isExpanded,
                   View convertView, ViewGroup parent) {
     PlaceNum gData= (PlaceNum) getGroup(groupPosition);

     if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_group, null);
     }

     TextView txtProName= (TextView) convertView.findViewById(R.id.txtprovince);
     txtProName.setText(Html.fromHtml("<b>"+gData.getPlace()+"</b>"));
     TextView txtNum= (TextView) convertView.findViewById(R.id.txtpnum);
     txtNum.setText(Html.fromHtml("<b>"+gData.getNum()+"</b>"));

     return convertView;
   }

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

   @Override
   public boolean isChildSelectable(int groupPosition, int childPosition) {
     return true;
   }
}




Here is the code of the MainActity class to setup the expandable list, and add header and data to the list.


import android.support.v7.app.ActionBarActivity;
import android.view.ViewGroup;
import android.widget.ExpandableListView;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class MainActivity extends ActionBarActivity {
   ExpandableListView expListView;
   ExpandableListAdapter expandableListAdapter;
   ArrayList<PlaceNum> listGroupTitles;
   HashMap<String, List<PlaceNum>> listDataMembers;

   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     // Get the expandable list
     expListView = (ExpandableListView) findViewById(R.id.lvExp);
     // Inflate header view
     ViewGroup headerView = (ViewGroup)getLayoutInflater().inflate(R.layout.list_header,expListView,false);
     // Add header view to the expandable list
     expListView.addHeaderView(headerView);
     // Setting up list
     setUpExpList();
     expandableListAdapter= new ExpandableListAdapter(this, listGroupTitles, listDataMembers);
     // Setting list adapter
     expListView.setAdapter(expandableListAdapter);

   }

   private void setUpExpList() {
     listGroupTitles= new ArrayList<PlaceNum>();
     listDataMembers= new HashMap<String, List<PlaceNum>>();
     // Adding province names and number of population as groups
     listGroupTitles.add(new PlaceNum("Kandal",123333));
     listGroupTitles.add(new PlaceNum("Takeo",208990));
     // Adding district names and number of population as children
     List<PlaceNum> p1Districts= new ArrayList<PlaceNum>();
     p1Districts.add(new PlaceNum("Kandal Steung",30000));
     p1Districts.add(new PlaceNum("Ksach Kandal",45000));
     p1Districts.add(new PlaceNum("Mokkompol", 48333));
     List<PlaceNum> p2Districts= new ArrayList<PlaceNum>();
     p2Districts.add(new PlaceNum("Bati",30400));
     p2Districts.add(new PlaceNum("Tramkok",55100));
     p2Districts.add(new PlaceNum("Daun Keo",123490));
     listDataMembers.put(listGroupTitles.get(0).getPlace(), p1Districts);
     listDataMembers.put(listGroupTitles.get(1).getPlace(),p2Districts);
   }
}

Posted by: Dara | post date: 04-01-2015 | Subject: Android Apps Development

write programming tip




This website intents to provide free and high quality tutorials, examples, exercises and solutions, questions and answers of programming and scripting languages:
C, C++, C#, Java, VB.NET, Python, VBA,PHP & Mysql, SQL, JSP, ASP.NET,HTML, CSS, JQuery, JavaScript and other applications such as MS Excel, MS Access, and MS Word. However, we don't guarantee all things of the web are accurate. If you find any error, please report it then we will take actions to correct it as soon as possible.