androidcheckboxradio-buttonexpandablelistviewitemrenderer

ANDROID - ExpandableListView


Im trying to figure out how to build a view that contains (many of):

...

...

The point is that parent has to be checkable and based on that children have to change the icon. Can some1 point me into the right direction, because from what i found nothing seems to work for me.


Solution

  • I assume, you have your data structured somehow, like: ArrayList where

    If so, you only have to do two things:

    1. create proper layouts for your parent item renderer and child item renderer
    2. expand BaseExpandableListAdapter to build up the list yourself.

    Here is a small sample about what's in my mind:
    layout/grouprow.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout android:orientation="horizontal"
        android:gravity="fill" android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- PARENT -->
        <TextView android:id="@+id/parentname" android:paddingLeft="5px"
            android:paddingRight="5px" android:paddingTop="3px"
            android:paddingBottom="3px" android:textStyle="bold" android:textSize="18px"
            android:layout_gravity="fill_horizontal" android:gravity="left"
            android:layout_height="wrap_content" android:layout_width="wrap_content" />
        <CheckBox android:id="@+id/checkbox" android:focusable="false" 
            android:layout_alignParentRight="true" android:freezesText="false"
            android:layout_width="wrap_content" android:layout_height="wrap_content" 
            android:layout_marginTop="5px" />
    </RelativeLayout>
    

    layout/childrow.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="wrap_content" android:padding="0px">
        <!-- CHILD -->
        <TextView android:id="@+id/childname" android:paddingLeft="15px" 
            android:paddingRight="5px" android:focusable="false" android:textSize="14px"
            android:layout_marginLeft="10px" android:layout_marginRight="3px" 
            android:layout_width="fill_parent" android:layout_height="wrap_content" />
    </LinearLayout>
    

    MyELAdapter class: I've declared this as an inner class of MyExpandableList, so i could reach the list of parents directly, without having to pass it as parameter.

    private class MyELAdapter extends BaseExpandableListAdapter
    {
        private LayoutInflater inflater;
    
        public MyELAdapter()
        {
            inflater = LayoutInflater.from(MyExpandableList.this);
        }
    
        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, 
                View convertView, ViewGroup parentView)
        {
            final Parent parent = parents.get(groupPosition);
            convertView = inflater.inflate(R.layout.grouprow, parentView, false);
            ((TextView) convertView.findViewById(R.id.parentname)).setText(parent.getName());
            CheckBox checkbox = (CheckBox) convertView.findViewById(R.id.checkbox);
            checkbox.setChecked(parent.isChecked());
            checkbox.setOnCheckedChangeListener(new CheckUpdateListener(parent));
            if (parent.isChecked())
                convertView.setBackgroundResource(R.color.red);
            else
                convertView.setBackgroundResource(R.color.blue);
            return convertView;
        }
    
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 
                View convertView, ViewGroup parentView)
        {
            final Parent parent = parents.get(groupPosition);
            final Child child = parent.getChildren().get(childPosition);
            convertView = inflater.inflate(R.layout.childrow, parentView, false);
            ((TextView) convertView.findViewById(R.id.childname)).setText(child.getName());
            return convertView;
        }
    
        @Override
        public Object getChild(int groupPosition, int childPosition)
        {
            return parents.get(groupPosition).getChildren().get(childPosition);
        }
    
        @Override
        public long getChildId(int groupPosition, int childPosition)
        {
            return childPosition;
        }
    
        @Override
        public int getChildrenCount(int groupPosition)
        {
            return parents.get(groupPosition).getChildren().size();
        }
    
        @Override
        public Object getGroup(int groupPosition)
        {
            return parents.get(groupPosition);
        }
    
        @Override
        public int getGroupCount()
        {
            return parents.size();
        }
    
        @Override
        public long getGroupId(int groupPosition)
        {
            return groupPosition;
        }
    
        @Override
        public void notifyDataSetChanged()
        {
            super.notifyDataSetChanged();
        }
    
        @Override
        public boolean isEmpty()
        {
            return ((parents == null) || parents.isEmpty());
        }
    
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition)
        {
            return true;
        }
    
        @Override
        public boolean hasStableIds()
        {
            return true;
        }
    
        @Override
        public boolean areAllItemsEnabled()
        {
            return true;
        }
    }
    

    You must already have a public class MyExpandableList extends ExpandableListActivity which has a member:

    private ArrayList<Parent> parents;
    

    after you assign a value to this member / load the list of parents, you should also attach your adapter to this view:

    this.setListAdapter(new MyELAdapter());
    

    and that's it. You have a checkable-expandable list, and in the CheckUpdateListener's onCheckedChanged(CompoundButton buttonView, boolean isChecked) method you can update your parent object's checked state.

    Note, that the background color is determined in the getGroupView method, so you don't have to change it anywhere, just call the adapter's notifyDataSetChanged() method if needed.

    Update

    you can download the sample source code from this link. It is an eclipse project, but if you are using other developer environment, just simply copy the necessary source files (java + xml).