Labels

‘Google Play again alcohol analytics Android Android Control Android Developer Android ebook Android N Android Studio Android Wear AndroidDevStory androidn AndroidWear anime Apps average bag beach benidorm beta testing betatesting GooglePlayforFamilies birthday BLT buildingforbillions camden camera cat ears charm christmas Christmas Countdown Clock chrome circle lenses Clock coat coffee collar Connectivity cosplay Countdown craft CultureAlley curl cute Develop Developer Preview developerstory developerstory developerconsole Distribute DIY drunk Education engagement exhibition families fashion Featured Featured’ felt fox freshers friends funny Games geek ghibli Google I/O Google Play Google Play Games Google Play games services GooglePlay gothic lolita gyaru hair halloween hand made hangover happy harry belafonte havea HelloEnglish herbie hancock hiragana Hitman Reborn holiday home hood hoodie hot chocolate house Hutch i'm back instagram iOS Control japanese japanese lolita javea kawaii kawaii it yourself kitty and the bulldog KIY knitting la mort learning life lightning lolita london look love love lunch machine madoka kaname maid maid cafe make-up make-up tutorial mariscos recio MaterialDesign me medieval mobile vision APIs monetization museum music Naruto Clock Naruto Flash Game NBU NDK needles neko nerd new New Year Countdown Clock oh One Piece Flash Clock Onee-chan outfit owl pan party peter peter pan photography pink player pool punk lolita purikura Reborn record red riding hood sea Security sewing shoes sorry spain store listing experiments story Storytoys student sunny sunshine sweet lolita table football tail tan to today totoro trying tutorial Udacity uni vam VandA victoria and albert vinyl wear well wifi wig winter wool xabia yarn zombie

How to create custom ExpandableListView in Android


From Developer.android.com: “A view that shows items in a vertically scrolling two-level list. This differs from the ListView by allowing two levels: groups which can individually be expanded to show its children. The items come from the ExpandableListAdapter associated with this view”

In this tutorial, we show you how to create a custom ExpandableListView with some images, texts... We want to make some groups of car and customize them with image, text and a checkbox. In each group, we will contain a few different cars, in particular each children row has to contain: an image and the name of the car.

Here is a result of this tutorial:

expandable list view example


This project is developed in Eclipse 4.2.0.

1. Make application interface: The main layout of this app demo have a text view, a button and an expandable list view.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
   
    <LinearLayout android:id="@+id/linear1"
             android:orientation="horizontal"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentBottom="true" 
                 android:background="@android:color/holo_blue_dark"
                 android:gravity="center">    
             <Button 
                 android:id="@+id/btn1"
                 android:layout_width="180dp"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="5dp"
                 android:layout_marginBottom="5dp"
                 android:textSize="22dp"
                 android:text="Buy all cars you have selected"  />
     </LinearLayout>  
    
    <ExpandableListView
        android:id="@+id/expandableListView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/linear1"
        android:layout_below="@+id/linear2"
        android:groupIndicator="@drawable/group_indicator_selector"
        android:background="@android:color/holo_blue_light"  >
        </ExpandableListView>
       
    <LinearLayout android:id="@+id/linear2"
             android:orientation="vertical"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentTop="true"
             android:background="@android:color/holo_blue_dark"
             android:gravity="center">      
        <TextView
                android:id="@+id/text_intro"
                android:textSize="20sp"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:gravity="center_vertical|center_horizontal"
                android:textColor= "#FFFFFF"
                android:text="Select cars you want to buy" />
     </LinearLayout>    
    
</RelativeLayout>
For android:groupIndicator of expandable list, create res/drawable/group_indicator_selector.xmland parse all xml content below:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_expanded="true"android:drawable="@drawable/group_indicator_expanded"/>
    <item android:drawable="@drawable/group_indicator"/>
</selector>
Now is the time we customize our expandable list view by create the layout for each group item and child item of it:
For group item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center_vertical">
        <CheckBox android:id="@+id/cbx1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:layout_alignParentRight="true"
        android:button="@drawable/checkbox_selector"
        />
        <ImageView android:id="@+id/image1"
        android:src="@drawable/ic_launcher"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginLeft="25dp"
       
        />
    <TextView
        android:id="@+id/text1"
        android:textSize="20sp"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginLeft="95dp" android:gravity="center_vertical"
        android:text="TextView"
            android:textColor= "#000000"/>
</RelativeLayout>
Customize checkbox in group item with android:button attribute by make a checkbox_selector.xml in drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
    android:drawable="@drawable/check" />
<item android:state_checked="false"
    android:drawable="@drawable/uncheck" />
</selector>
For children item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center_vertical">
        <ImageView android:id="@+id/image1"
        android:src="@drawable/ic_launcher"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginLeft="25dp"       
        />
    <TextView
        android:id="@+id/text1"
        android:textSize="16sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="95dp"
        android:gravity="center"
        android:text="TextView" 
        android:textColor = "#000000"/>
</RelativeLayout>

Thus we have completed the design of the interface. Now begin make some codes.

2. Code
2.1. We start by creating the SampleExpandableListAdapter for ExpandableListView
package com.example.expandablelist;

import java.util.HashMap; 
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ExpandableListAdapter;

public class SampleExpandableListAdapter extends BaseExpandableListAdapter implements ExpandableListAdapter  {
        public Context context;
        CheckBox checkBox;
    private LayoutInflater vi;
    private String[][] data;
    int _objInt;
    public static Boolean checked[] = new Boolean[1];
 
    HashMap<Long,Boolean> checkboxMap = new HashMap<Long,Boolean>();
    private static final int GROUP_ITEM_RESOURCE = R.layout.group_item;
    private static final int CHILD_ITEM_RESOURCE = R.layout.child_item;
    public String []check_string_array;
   
    public SampleExpandableListAdapter(Context context, Activity activity, String[][] data) {
        this.data = data;
        this.context = context;
        vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       
        _objInt = data.length;
        check_string_array = new String[_objInt];
        popolaCheckMap();
    }
    public void popolaCheckMap(){

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); 
        String buffer = null;
       
        for(int i=0; i<_objInt; i++){
                buffer = settings.getString(String.valueOf((int)i),"false");
                if(buffer.equals("false"))
                        checkboxMap.put((long)i, false);
                else checkboxMap.put((long)i, true);
        }
    }
   
    public class CheckListener implements OnCheckedChangeListener{

        long pos;

        public void setPosition(long p){
            pos = p;
        }

        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
                Log.i("checkListenerChanged", String.valueOf(pos)+":"+String.valueOf(isChecked));
            checkboxMap.put(pos, isChecked);
            if(isChecked == true) check_string_array[(int)pos] = "true";
            else                                  check_string_array[(int)pos] = "false";
           // save checkbox state of each group
            SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);                
            SharedPreferences.Editor preferencesEditor = settings.edit();
            preferencesEditor.putString(String.valueOf((int)pos), check_string_array[(int)pos]);
            preferencesEditor.commit();
        }
    }
    public String getChild(int groupPosition, int childPosition) {
        return data[groupPosition][childPosition];
    }

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

    public int getChildrenCount(int groupPosition) {
        return data[groupPosition].length;
    }

    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        View v = convertView;
        String child = getChild(groupPosition, childPosition);
        int id_res = 0;
        if(groupPosition == 0){
                if(childPosition == 0) id_res = R.drawable.audi_a4;
                if(childPosition == 1) id_res = R.drawable.audi_q7;
                if(childPosition == 2) id_res = R.drawable.audi_r8;
        }
        else if(groupPosition == 1){
                if(childPosition == 0) id_res = R.drawable.bmw_m6;
                if(childPosition == 1) id_res = R.drawable.bmw_x6;
        }
        else if(groupPosition == 2){
                if(childPosition == 0) id_res = R.drawable.ferrari_enzo;
                if(childPosition == 1) id_res = R.drawable.ferrari_f430;
                if(childPosition == 2) id_res = R.drawable.ferrari_f430_italia;
        }
       
        if (child != null) {
            v = vi.inflate(CHILD_ITEM_RESOURCE, null);
            ViewHolder holder = new ViewHolder(v);
            holder.text.setText(Html.fromHtml(child));
           
            holder.imageview.setImageResource(id_res);
        }
        return v;
    }
    public String getGroup(int groupPosition) {
        return "group-" + groupPosition;
    }
    public int getGroupCount() {
        return data.length;
    }
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        View v = convertView;
        String group = null;
        int id_res = 0;
        long group_id = getGroupId(groupPosition);
        if(group_id == 0){
                group = "Audi";
                id_res = R.drawable.audi;
        }
        else if(group_id == 1){
                group = "BMW";
                id_res = R.drawable.bmw;
        }
        else if(group_id == 2){
                group = "Ferrari";
                id_res = R.drawable.ferrari;
        }
       
        if (group != null) {
            v = vi.inflate(GROUP_ITEM_RESOURCE, null);
            ViewHolder holder = new ViewHolder(v);

            holder.text.setText(Html.fromHtml(group));
            holder.imageview.setImageResource(id_res);
            holder.checkbox.setFocusable(false);
            CheckListener checkL = new CheckListener();
            checkL.setPosition(group_id);
            holder.checkbox.setOnCheckedChangeListener(checkL);
            holder.checkbox.setChecked(checkboxMap.get(group_id)); 
        }
        return v;
    }
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
    public boolean hasStableIds() {
        return true;
    }
}
2.2. Create view holder class to hold all component of group item or child item
package com.example.expandablelist;

import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;

public class ViewHolder {
    public TextView text;
    public CheckBox checkbox;
    public ImageView imageview;
    public ViewHolder(View v) {
        this.text = (TextView)v.findViewById(R.id.text1);
        this.checkbox = (CheckBox)v.findViewById(R.id.cbx1);
        this.imageview = (ImageView)v.findViewById(R.id.image1);
    }

}
2.3. Then in the main activity, set adapter for expandable list view and when user click on the button will show all groups on expandable list view has checked on checkbox by Toast Message.
package com.example.expandablelist;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences; 
import android.view.View;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.Toast;
public class ExpandablelistActivity extends Activity {
        final Context context = this;
    private static final String[][] data = {{"audia4","audiq7","audir8"},{"bmwm6","bmwx6"},{"ferrarienzo","ferrarif430","ferrarif430italia"}};
    privateExpandableListView expandableListView;
    Button button1;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expandablelist);
        button1 = (Button)findViewById(R.id.btn1);
        expandableListView = (ExpandableListView)findViewById(R.id.expandableListView1);
        expandableListView.setAdapter(new SampleExpandableListAdapter(context, this, data));
       
        button1.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                // TODO Auto-generated method stub
                                SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); 
                        String buffer = null;
                        String output_String = "";
                        for(int i=0; i<3; i++){
                                buffer = settings.getString(String.valueOf((int)i),"false");
                                if(buffer.equals("true"))
                                        output_String += "group " + i + " ";
                        }
                        output_String += "is checked";
                                Toast.makeText(ExpandablelistActivity.this, output_String, Toast.LENGTH_SHORT).show();
                        }
                });
    }
}

package DucNguyen.example.customlistview;
import java.util.List;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class FootballLegendListAdapter extends ArrayAdapter<FootballLegend> {
        private int                             resource;
        private LayoutInflater  inflater;
        private Context                 context;
        public FootballLegendListAdapter ( Context ctx, int resourceId, List<FootballLegend> objects) {
                super( ctx, resourceId, objects );
                resource = resourceId;
                inflater = LayoutInflater.from( ctx );
                context=ctx;
        }
        @Override
        public View getView ( int position, View convertView, ViewGroup parent ) {
                convertView = ( RelativeLayout ) inflater.inflate( resource, null );
                FootballLegend Legend = getItem( position );
                                TextView legendName = (TextView) convertView.findViewById(R.id.legendName);
                legendName.setText(Legend.getName());
                 
                TextView legendBorn = (TextView) convertView.findViewById(R.id.legendBorn);
                legendBorn.setText(Legend.getNick());
                 
                ImageView legendImage = (ImageView) convertView.findViewById(R.id.legendImage);
                String uri = "drawable/" + Legend.getImage();
            int imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
            Drawable image = context.getResources().getDrawable(imageResource);
            legendImage.setImageDrawable(image);
           
            ImageView NationImage = (ImageView) convertView.findViewById(R.id.Nation);
                uri = "drawable/" + Legend.getNation();
            imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
            image = context.getResources().getDrawable(imageResource);
            NationImage.setImageDrawable(image);

                return convertView;
        }
}

3.DEMO
3.1. Run application
Android expandable list view example


3.2. Click on a button
Android expandable list view example

You can download all source codes of this tutorial from here.
Reference: http://www.hrupin.com/2012/08/how-to-create-custom-groupindicator-for-expandablelistview-group

0 Response to "How to create custom ExpandableListView in Android"

Post a Comment