Android ExpandableListView Example.
Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.as400samplecode"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
Application main Layout - activity_main.xml
<?xml version="1.0" encoding="UTF-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <SearchView android:id="@+id/search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:iconifiedByDefault="false" /> <ExpandableListView android:id="@+id/expandableList" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/search" /> </RelativeLayout>
ExpandableListView Child Row Layout - child_row.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android"> <TextView android:id="@+id/code" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:paddingLeft="35sp" android:paddingRight="10dp" android:text="USA" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/code" android:text="United States Of America" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/population" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:paddingRight="5dp" android:text="200,000,000" android:textAppearance="?android:attr/textAppearanceMedium" /> </RelativeLayout>
ExpandableListView Header Row Layout - group_row.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/heading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="35sp" android:textAppearance="?android:attr/textAppearanceLarge" android:textStyle="bold" /> </LinearLayout>
Child Row Country Object - Country.java
package com.as400samplecode;
public class Country {
 
 private String code = "";
 private String name = "";
 private int population = 0;
 
 public Country(String code, String name, int population) {
  super();
  this.code = code;
  this.name = name;
  this.population = population;
 }
 
 public String getCode() {
  return code;
 }
 public void setCode(String code) {
  this.code = code;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getPopulation() {
  return population;
 }
 public void setPopulation(int population) {
  this.population = population;
 }
 
}
Group Heading Continent Object - Continent.java
package com.as400samplecode;
import java.util.ArrayList;
public class Continent {
 
 private String name;
 private ArrayList<Country> countryList = new ArrayList<Country>();
 
 public Continent(String name, ArrayList<Country> countryList) {
  super();
  this.name = name;
  this.countryList = countryList;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public ArrayList<Country> getCountryList() {
  return countryList;
 }
 public void setCountryList(ArrayList<Country> countryList) {
  this.countryList = countryList;
 };
 
}
Custom BaseExpandableListAdapter with filter - MyListAdapter.java
package com.as400samplecode;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
public class MyListAdapter extends BaseExpandableListAdapter {
 private Context context;
 private ArrayList<Continent> continentList;
 private ArrayList<Continent> originalList;
 
 public MyListAdapter(Context context, ArrayList<Continent> continentList) {
  this.context = context;
  this.continentList = new ArrayList<Continent>();
  this.continentList.addAll(continentList);
  this.originalList = new ArrayList<Continent>();
  this.originalList.addAll(continentList);
 }
 
 @Override
 public Object getChild(int groupPosition, int childPosition) {
  ArrayList<Country> countryList = continentList.get(groupPosition).getCountryList();
  return countryList.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) {
  
  Country country = (Country) getChild(groupPosition, childPosition);
  if (view == null) {
   LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   view = layoutInflater.inflate(R.layout.child_row, null);
  }
  
  TextView code = (TextView) view.findViewById(R.id.code);
  TextView name = (TextView) view.findViewById(R.id.name);
  TextView population = (TextView) view.findViewById(R.id.population);
  code.setText(country.getCode().trim());
  name.setText(country.getName().trim());
  population.setText(NumberFormat.getNumberInstance(Locale.US).format(country.getPopulation()));
  
  return view;
 }
 @Override
 public int getChildrenCount(int groupPosition) {
  
  ArrayList<Country> countryList = continentList.get(groupPosition).getCountryList();
  return countryList.size();
 }
 @Override
 public Object getGroup(int groupPosition) {
  return continentList.get(groupPosition);
 }
 @Override
 public int getGroupCount() {
  return continentList.size();
 }
 @Override
 public long getGroupId(int groupPosition) {
  return groupPosition;
 }
 @Override
 public View getGroupView(int groupPosition, boolean isLastChild, View view,
   ViewGroup parent) {
  
  Continent continent = (Continent) getGroup(groupPosition);
  if (view == null) {
   LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   view = layoutInflater.inflate(R.layout.group_row, null);
  }
  
  TextView heading = (TextView) view.findViewById(R.id.heading);
  heading.setText(continent.getName().trim());
  
  return view;
 }
 @Override
 public boolean hasStableIds() {
  return true;
 }
 @Override
 public boolean isChildSelectable(int groupPosition, int childPosition) {
  return true;
 }
 
 public void filterData(String query){
  
  query = query.toLowerCase();
  Log.v("MyListAdapter", String.valueOf(continentList.size()));
  continentList.clear();
  
  if(query.isEmpty()){
   continentList.addAll(originalList);
  }
  else {
   
   for(Continent continent: originalList){
    
    ArrayList<Country> countryList = continent.getCountryList();
    ArrayList<Country> newList = new ArrayList<Country>();
    for(Country country: countryList){
     if(country.getCode().toLowerCase().contains(query) ||
       country.getName().toLowerCase().contains(query)){
      newList.add(country);
     }
    }
    if(newList.size() > 0){
     Continent nContinent = new Continent(continent.getName(),newList);
     continentList.add(nContinent);
    }
   }
  }
  
  Log.v("MyListAdapter", String.valueOf(continentList.size()));
  notifyDataSetChanged();
  
 }
}
Application Activity - MainActivity.java
package com.as400samplecode;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.view.Menu;
import android.widget.ExpandableListView;
import android.widget.SearchView;
public class MainActivity extends Activity implements  
 SearchView.OnQueryTextListener, SearchView.OnCloseListener{
 private SearchView search;
 private MyListAdapter listAdapter;
 private ExpandableListView myList;
 private ArrayList<Continent> continentList = new ArrayList<Continent>();
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
  search = (SearchView) findViewById(R.id.search);
  search.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
  search.setIconifiedByDefault(false);
  search.setOnQueryTextListener(this);
  search.setOnCloseListener(this);
  
  //display the list
  displayList();
  //expand all Groups
  expandAll();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    //method to expand all groups
 private void expandAll() {
  int count = listAdapter.getGroupCount();
  for (int i = 0; i < count; i++){
   myList.expandGroup(i);
  }
 }
 
 //method to expand all groups
 private void displayList() {
  
  //display the list
  loadSomeData();
  
  //get reference to the ExpandableListView
  myList = (ExpandableListView) findViewById(R.id.expandableList);
  //create the adapter by passing your ArrayList data
  listAdapter = new MyListAdapter(MainActivity.this, continentList);
  //attach the adapter to the list
  myList.setAdapter(listAdapter);
  
 }
 
 private void loadSomeData() {
  
  ArrayList<Country> countryList = new ArrayList<Country>();
  Country country = new Country("BMU","Bermuda",10000000);
  countryList.add(country);
  country = new Country("CAN","Canada",20000000);
  countryList.add(country);
  country = new Country("USA","United States",50000000);
  countryList.add(country);
  
  Continent continent = new Continent("North America",countryList);
  continentList.add(continent);
  
  countryList = new ArrayList<Country>();
  country = new Country("CHN","China",10000100);
  countryList.add(country);
  country = new Country("JPN","Japan",20000200);
  countryList.add(country);
  country = new Country("THA","Thailand",50000500);
  countryList.add(country);
  
  continent = new Continent("Asia",countryList);
  continentList.add(continent);
  
 }
 @Override
 public boolean onClose() {
  listAdapter.filterData("");
  expandAll();
  return false;
 }
 @Override
 public boolean onQueryTextChange(String query) {
  listAdapter.filterData(query);
  expandAll();
  return false;
 }
 @Override
 public boolean onQueryTextSubmit(String query) {
  listAdapter.filterData(query);
  expandAll();
  return false;
 }
}


2 comments:
how to get country name (string) or population from .setOnChildClickListener ?? thanks in advance!
about my question before: .setOnChildClickListener I already get solution, so I need to add:
continentList.get(groupPosition).getCountryList().get(childPosition).getName()
but now, I have another problem, when I use search function/filter, Why doesn't my ListView show the new data when I call notifyDataSetChanged ? pls help
Post a Comment
NO JUNK, Please try to keep this clean and related to the topic at hand.
Comments are for users to ask questions, collaborate or improve on existing.