Android Working with Expandable List View

activity_main.xml

<?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="match_parent"
    tools:context="iterator.ir.a042.MainActivity">

    <ExpandableListView
        android:id="@+id/expandableListViewProvinces"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />
</RelativeLayout>

HeaderInfo.java

public class HeaderInfo {

    public String getProvoniceName() {
        return provoniceName;
    }

    public void setProvoniceName(String provoniceName) {
        this.provoniceName = provoniceName;
    }

    private String provoniceName;

    public int getPopulation() {
        return population;
    }

    private int population;

    public ArrayList<DetailInfo> getCities() {
        return cities;
    }

    public void setCities(ArrayList<DetailInfo> cities) {
        this.cities = cities;

        int pop=0;

        for (DetailInfo info:cities)
        {
            pop+=info.getPopulation();
        }

        this.population=pop;
    }

    private ArrayList<DetailInfo> cities=new ArrayList<>();

}

DetailInfo.java

public class DetailInfo {

    private String cityName;

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    private int population;
}

CustomAdapter.java

public class CustomAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<HeaderInfo> cInfo;

    public CustomAdapter(Context context,ArrayList<HeaderInfo> cInfo)
    {
        this.context=context;
        this.cInfo=cInfo;
    }

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

    @Override
    public int getChildrenCount(int groupPosition) {
        return cInfo.get(groupPosition).getCities().size();
    }

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

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return cInfo.get(groupPosition).getCities().get(childPosition);
    }

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

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

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

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        View view=convertView;

        if (view==null)
        {
            LayoutInflater layoutInflater=LayoutInflater.from(context);
            view=layoutInflater.inflate(R.layout.header_layout,parent,false);
        }

        HeaderInfo current=this.cInfo.get(groupPosition);

        if (current!=null)
        {
            TextView textViewProvinceName= (TextView) view.findViewById(R.id.textViewProvinceName);
            TextView textViewProvincePopulation= (TextView) view.findViewById(R.id.textViewProvincePopulation);

            textViewProvinceName.setText(current.getProvoniceName());
            textViewProvincePopulation.setText(String.valueOf(current.getPopulation()));
        }

        return view;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        View view=convertView;

        if (view==null)
        {
            LayoutInflater layoutInflater=LayoutInflater.from(context);
            view=layoutInflater.inflate(R.layout.detail_layout,parent,false);
        }

        DetailInfo current=this.cInfo.get(groupPosition).getCities().get(childPosition);

        if (current!=null)
        {
            TextView textViewCityName= (TextView) view.findViewById(R.id.textViewCityName);
            TextView textViewCityPopulation= (TextView) view.findViewById(R.id.textViewCityPopulation);

            textViewCityName.setText(current.getCityName());
            textViewCityPopulation.setText(String.valueOf(current.getPopulation()));
        }

        return view;
    }

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

MainActivity.java

public class MainActivity extends AppCompatActivity {

    ExpandableListView expandableListViewProvinces;
    ArrayList<HeaderInfo> provonices;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GenerateData();

        expandableListViewProvinces= (ExpandableListView) findViewById(R.id.expandableListViewProvinces);
        CustomAdapter adapter=new CustomAdapter(this,provonices);
        expandableListViewProvinces.setAdapter(adapter);
    }

    private void GenerateData()
    {
        provonices=new ArrayList<>();


        DetailInfo detailInfo1=new DetailInfo();
        detailInfo1.setCityName("Rasht");
        detailInfo1.setPopulation(1000000);


        DetailInfo detailInfo2=new DetailInfo();
        detailInfo2.setCityName("Lahijan");
        detailInfo2.setPopulation(700000);

        DetailInfo detailInfo3=new DetailInfo();
        detailInfo3.setCityName("Anzali");
        detailInfo3.setPopulation(800000);

        DetailInfo detailInfo4=new DetailInfo();
        detailInfo4.setCityName("Fouman");
        detailInfo4.setPopulation(200000);

        ArrayList<DetailInfo> cities1=new ArrayList<>();
        cities1.add(detailInfo1);
        cities1.add(detailInfo2);
        cities1.add(detailInfo3);
        cities1.add(detailInfo4);

        HeaderInfo headerInfo1=new HeaderInfo();
        headerInfo1.setProvoniceName("Guilan");
        headerInfo1.setCities(cities1);

        DetailInfo detailInfo5=new DetailInfo();
        detailInfo5.setCityName("Tehran");
        detailInfo5.setPopulation(10000000);


        DetailInfo detailInfo6=new DetailInfo();
        detailInfo6.setCityName("Hashtgerd");
        detailInfo6.setPopulation(700000);


        ArrayList<DetailInfo> cities2=new ArrayList<>();
        cities2.add(detailInfo5);
        cities2.add(detailInfo6);


        HeaderInfo headerInfo2=new HeaderInfo();
        headerInfo2.setProvoniceName("Tehran");
        headerInfo2.setCities(cities2);


        DetailInfo detailInfo7=new DetailInfo();
        detailInfo7.setCityName("Qazvin");
        detailInfo7.setPopulation(1000000);


        ArrayList<DetailInfo> cities3=new ArrayList<>();
        cities3.add(detailInfo7);

        HeaderInfo headerInfo3=new HeaderInfo();
        headerInfo3.setProvoniceName("Qazvin");
        headerInfo3.setCities(cities3);

        provonices.add(headerInfo1);
        provonices.add(headerInfo2);
        provonices.add(headerInfo3);
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/042