Pages

Monday, June 27, 2011

Custom Expandable Listview

Hi expandable List-view is two level tree view provided by Android. In this view contains two types of categories. First type is Group-Elements and second one is Child-Elements. And also called parent and child elements. The main aim of this example is customise the expandable list-view as picture a shown bellow. Means I covered some important topics about expandable list-view when I face in my experience.

Below code is main.xml contains the expandable list-view.
main.xml


 
     
 
            

group_row.xml this is contains the layout for Expandable list view group view structure.
group_row.xml


         
         

child_row.xml this is contains the layout for Expandable list view group structure.
child_row.xml



    
         

First read the reference of the expandable listview from xml to activity class.
public class ExpList extends ExpandableListActivity
{
 /**
  * strings for group elements
  */
    static final String arrGroupelements[] = 
    {
   "India",
   "Australia",
   "England",
   "South Africa"
 };

    /**
  * strings for child elements
  */
 static final String arrChildelements[][] = 
 {
   {
  "Sachin Tendulkar",
  "Raina",
  "Dhoni",
  "Yuvi"
   },
   {
  "Ponting",
  "Adam Gilchrist",
  "Michael Clarke"
   },
   {
  "Andrew Strauss",
  "kevin Peterson",
  "Nasser Hussain"
   },
   {
  "Graeme Smith",
  "AB de villiers",
  "Jacques Kallis"
   }
    };

 DisplayMetrics metrics;
 int width;
 ExpandableListView expList;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        expList = getExpandableListView();
        metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        width = metrics.widthPixels;
        //this code for adjusting the group indicator into right side of the view
        expList.setIndicatorBounds(width - GetDipsFromPixel(50), width - GetDipsFromPixel(10));
        expList.setAdapter(new ExpAdapter(this));
  
  expList.setOnGroupExpandListener(new OnGroupExpandListener()
  {
   @Override
   public void onGroupExpand(int groupPosition) 
   {
    Log.e("onGroupExpand", "OK");
   }
  });
  
  expList.setOnGroupCollapseListener(new OnGroupCollapseListener()
  {
   @Override
   public void onGroupCollapse(int groupPosition) 
   {
    Log.e("onGroupCollapse", "OK");
   }
  });
  
  expList.setOnChildClickListener(new OnChildClickListener()
  {
   @Override
   public boolean onChildClick(ExpandableListView parent, View v,
     int groupPosition, int childPosition, long id) {
    Log.e("OnChildClickListener", "OK");
    return false;
   }
  });
    }
  
    public int GetDipsFromPixel(float pixels)
    {
     // Get the screen's density scale
     final float scale = getResources().getDisplayMetrics().density;
     // Convert the dps to pixels, based on density scale
     return (int) (pixels * scale + 0.5f);
    }
}

For customising the Exp Listview main thing is adapter. Android provides BaseExpandableListAdapter for customising the view. Bellow is the code for design of Adapter.
/**
     * This is adapter for expandable list-view for constructing the group and child elements.
     */
 public class ExpAdapter extends BaseExpandableListAdapter {

  private Context myContext;
  public ExpAdapter(Context context) {
   myContext = context;
  }
  @Override
  public Object getChild(int groupPosition, int childPosition) {
   return null;
  }

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

  @Override
  public View getChildView(int groupPosition, int childPosition,
    boolean isLastChild, View convertView, ViewGroup parent) {
   
   if (convertView == null) {
    LayoutInflater inflater =  (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.child_row, null);
   }
   
   TextView tvPlayerName = (TextView) convertView.findViewById(R.id.tvPlayerName);
   tvPlayerName.setText(arrChildelements[groupPosition][childPosition]);
   
   return convertView;
  }

  @Override
  public int getChildrenCount(int groupPosition) {
   return arrChildelements[groupPosition].length;
  }

  @Override
  public Object getGroup(int groupPosition) {
   return null;
  }

  @Override
  public int getGroupCount() {
   return arrGroupelements.length;
  }

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

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

   if (convertView == null) {
    LayoutInflater inflater =  (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = inflater.inflate(R.layout.group_row, null);
   }
   
   TextView tvGroupName = (TextView) convertView.findViewById(R.id.tvGroupName);
   tvGroupName.setText(arrGroupelements[groupPosition]);
   
   return convertView;
  }

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

  @Override
  public boolean isChildSelectable(int groupPosition, int childPosition) {
   return true;
  }
 }
group_indicator.xml
This the code for changing the default indicator image.


    
    
    

11 comments:

  1. thanks a lot for providing this material.it is very helpful for me..

    ReplyDelete
  2. You explain expandable list view in nice manner. I have tried my best to explain the same. I have also created a simple demo and attach source code
    http://androidtrainningcenter.blogspot.in/2012/07/android-expandable-listview-simple.html. May it help some one.

    ReplyDelete
  3. Code is awfully formatted.

    child_row should be



    group_indicator.xml (rename ic_launcher to a drawable of your liking)









    Also ExpAdapter should be a class inside ExpList class

    ReplyDelete
  4. Hey.
    Nice job, but i found a little mistake in group_indicator.xml. Selector should look like this :

    <'item android:state_empty="true" android:drawable="@drawable/arrowright"/>
    <'item android:state_expanded="true" android:drawable="@drawable/arrowdown"/>
    <'item android:drawable="@drawable/arrowright"/>



    Items cannot be nested like in your example, otherwise arrowdown doesn't show up.

    Justyna

    ReplyDelete
    Replies
    1. Hi I did in correct manner but html coding problem I think. I changed now. Thank you for you suggestion.

      Delete
  5. hi sachin can you give me download link for this example with source code ?

    ReplyDelete
    Replies
    1. Hi Affab Ali actually I posted this post almost one and half year back. I don't have complete source code. I will develop this example again with latest android version reach you very soon...

      Delete
  6. Hi, actually im am doing a project work for school and i need to link an existing exapandable list found on à website (http://www.taxis-bleus.com/)(ADRESSE DE DÉPART ) to an expandable list which i created for an application. Clearly i want to see the same list of the website on my expandable list on my application.

    Thank you in advance

    ReplyDelete
  7. Add an image in drawable folder whose name is arrowright and arrowdown otherwise you also can give another imge

    ReplyDelete
    Replies
    1. Ok thank you. I will update this example soon....

      Delete
  8. Please guide me i am getting---------------Caused by: java.lang.UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView----------------

    ReplyDelete