Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Expandable list

I am trying to use a custom ExpandableListView with parent and child layout with a parent XML and child XML.

My data would be a server response. So I preferably would like to have data in the form of an Array List or Hash-map for parent and child layouts

I am enclosing the images of what I want.

Is there any way to change the expandable list arrow image(Default) by any + or - UI representation as shown below.

List

List1

Please suggest a tutorial or code logic for this specific situation .

like image 952
Arpit Garg Avatar asked Jun 30 '11 12:06

Arpit Garg


People also ask

What is expandable list view in android?

android.widget.ExpandableListView. 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.

How do you use expandable list view?

Android ExpandableListView is a view that shows items in a vertically scrolling two-level list. It differs from a ListView by allowing two levels which are groups that can be easily expanded and collapsed by touching to view and their respective children items.


2 Answers

After a R & D over expandable List I found that expandable List-view is a two level tree view provided by Android.

This view contains two types of categories.

First type is Group-Elements and second one is Child-Elements, also called parent and child elements.

The main aim of this example is to customize the expandable list-view as the picture in the question shows.

I have covered some important topics about expandable list-view that I faced during my experiences.

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

<!--?xml version="1.0" encoding="UTF-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">

     <expandablelistview android:id="@+id/android:list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:groupindicator="@drawable/group_indicator.xml">

     <textview android:id="@+id/android:empty" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/main_no_items">       
</textview></expandablelistview></linearlayout>

the group_row.xml is as follows that contains the layout for Expandable list group view structure.group_row.xml ?

     <textview android:id="@+id/tvGroupName" android:layout_width="wrap_content" android:layout_height="40dip" android:textsize="16sp" android:textstyle="bold" android:paddingleft="30dip" android:gravity="center_vertical">

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

<!--?xml version="1.0" encoding="utf-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="40dip" android:gravity="center_vertical">

    <textview android:id="@+id/tvPlayerName" android:paddingleft="50dip" android:textsize="14sp" android:layout_width="wrap_content" android:layout_height="30dip" android:gravity="center_vertical">

</textview></linearlayout>

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


if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
            expList.setIndicatorBounds(width - GetDipsFromPixel(50), width - GetDipsFromPixel(10));
        } else {
            expList.setIndicatorBoundsRelative(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.

 <?xml version="1.0" encoding="UTF-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_expanded="true" android:drawable="@drawable/friend_small" />
        <item android:drawable="@drawable/place_small" />
    </selector>
like image 148
Arpit Garg Avatar answered Oct 10 '22 22:10

Arpit Garg


you can change the indicator by calling setGroupIndicator

Expandable lists are able to show an indicator beside each item to display the item's current state (the states are usually one of expanded group, collapsed group, child, or last child). Use setChildIndicator(Drawable) or setGroupIndicator(Drawable) (or the corresponding XML attributes) to set these indicators (see the docs for each method to see additional state that each Drawable can have).

also, you need your own implementation of an ExpandableListAdapter. it's possible to inflate your own views for both parents and children in it.

like image 33
stefs Avatar answered Oct 10 '22 22:10

stefs