user2327556
user2327556

Reputation: 31

How to combine children and their header in ExpanadbleListView?

I am tying to find a way to combine the group view and the child views in a list like this

except that it will be an expandable list instead.

Thank you.

Upvotes: 3

Views: 1549

Answers (1)

anddev84
anddev84

Reputation: 1483

I've taken the liberty to draw up some sample code for this. It made the most sense to just create your own custom view extending from ExpandableListView (especially if you want the rounded corners), a custom adapter to handle the groups and children, and then have your main.xml just include multiple custom views. As you can see from the screenshot, I've managed to reproduce it pretty closely.

enter image description here

So here's the code:

RoundedExpandableListView.java

public class RoundedExpandableListView extends ExpandableListView {

    public RoundedExpandableListView(Context context) {
        super(context);
    }

    public RoundedExpandableListView(Context context, AttributeSet attrs) {
        super(context, attrs);

        // for setting the background color and rounded corners
        int bgColor = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "background", 0xffffff);
        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RoundedExpandableListView);
        int radius = a.getInteger(R.styleable.RoundedExpandableListView_radius, 0);
        PaintDrawable drawable = new PaintDrawable();
        drawable.getPaint().setColor(bgColor);
        drawable.setCornerRadius(radius);
        setBackgroundDrawable(drawable);
        a.recycle();
    }
}

GroupedViewAdapter.java

public class GroupedViewAdapter extends BaseExpandableListAdapter {

    private Context mContext;
    private String[] mGroups;
    private Object[][] mChildren;
    private int mGroupLayoutId;
    private int mChildLayoutId;
    private Drawable mTitleDrawable;

    public GroupedViewAdapter(Context c, String[] k, Object[][] v, int titleDrawableResId) {
        this(c, k, android.R.layout.simple_expandable_list_item_1, v,
                android.R.layout.simple_expandable_list_item_1, titleDrawableResId);
    }

    public GroupedViewAdapter(Context c, String[] k, int groupLayoutResId, Object[][] v,
            int childLayoutResId, int titleDrawableResId) {
        super();
        mContext = c;
        mGroups = k;
        mChildren = v;
        mGroupLayoutId = groupLayoutResId;
        mChildLayoutId = childLayoutResId;
        mTitleDrawable = mContext.getResources().getDrawable(titleDrawableResId);
        mTitleDrawable.setBounds(0, 0, 48, 48); // not necessarily the best way, but just to show example
    }

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

    @Override
    public int getChildrenCount(int groupPosition) {
        return (mChildren[groupPosition] == null) ? 0 : mChildren[groupPosition].length;
    }

    @Override
    public void onGroupCollapsed(int groupPosition) {
        super.onGroupCollapsed(groupPosition);
    }

    @Override
    public void onGroupExpanded(int groupPosition) {
        super.onGroupExpanded(groupPosition);
    }

    @Override
    public String getGroup(int groupPosition) {
        return mGroups[groupPosition];
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return (mChildren[groupPosition] == null) ? null : mChildren[groupPosition][childPosition];
    }

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

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

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

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {
        View v;
        if (convertView != null) {
            v = convertView;
        } else {
            LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = li.inflate(mGroupLayoutId, parent, false);
        }

        TextView tv = ((TextView) v);
        tv.setText(getGroup(groupPosition));
        tv.setTag(getGroupId(groupPosition));
        // set title group special properties
        if (groupPosition == 0) {
            tv.setTextSize(20);
            tv.setCompoundDrawables(mTitleDrawable, null, null, null);
        } else if (isExpanded) {
            tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_expanded, 0);
        } else {
            tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.icon_collapsed, 0);
        }

        return tv;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

        View v;
        if (convertView != null) {
            v = convertView;
        } else {
            LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = li.inflate(mChildLayoutId, parent, false);
        }

        TextView tv = ((TextView) v);
        tv.setText((String)getChild(groupPosition, childPosition));
        tv.setTag(getChildId(groupPosition, childPosition));

        return tv;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
}

MainActivity.java

public class MainActivity extends Activity {

    private RoundedExpandableListView mContact;
    private RoundedExpandableListView mAddress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mContact = (RoundedExpandableListView) findViewById(R.id.listview_contact);
        mAddress = (RoundedExpandableListView) findViewById(R.id.listview_address);
        mContact.setAdapter(new GroupedViewAdapter(this,
                getResources().getStringArray(R.array.contact_list_items), // I chose to create this directly in XML, but you can generate it via Java like I did the children below
                R.layout.drawer_list_item,
                createChildList(),
                R.layout.drawer_list_item,
                R.drawable.ic_action_email));
        mAddress.setAdapter(new GroupedViewAdapter(this,
                getResources().getStringArray(R.array.address_list_items),
                R.layout.drawer_list_item,
                createChildList(),
                R.layout.drawer_list_item,
                R.drawable.ic_action_map));
        mContact.setGroupIndicator(null); // since the adapter is changing how to show the group indicator icon
        mAddress.setGroupIndicator(null); // since the adapter is changing how to show the group indicator icon
    }

    private String[][] createChildList() {
        // Do stuff here to generate the list of children. Since the examples
        //   didn't have any, I didn't add any here.
        return null; // Change this once you have children
    }
}

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/com.example.sample"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#95c91d" >

    <com.example.sample.RoundedExpandableListView
        android:id="@+id/listview_contact"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginBottom="20dp"
        android:paddingLeft="10dp"
        android:background="#ffffff"
        local:radius="20" />

    <com.example.sample.RoundedExpandableListView
        android:id="@+id/listview_address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginBottom="20dp"
        android:paddingLeft="10dp"
        android:background="#ffffff"
        local:radius="20"
        android:layout_below="@+id/listview_contact" />
</RelativeLayout>

res/layout/drawer_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textSize="14sp"
    android:text="test"
    android:paddingTop="@dimen/list_item_margin"
    android:paddingRight="@dimen/list_item_margin"
    android:paddingBottom="@dimen/list_item_margin"
    android:drawableLeft="@android:drawable/ic_menu_manage"
    android:drawablePadding="12dp"
    />

res/values/attrs.xml (for creating custom attributes for your View)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundedExpandableListView">
        <attr name="radius" format="integer" />
    </declare-styleable>
</resources>

res/values/strings.xml

<!-- stuff up here -->

<string-array name="contact_list_items">
    <item name="item_title">Contact</item>
    <item name="item_number">+41 41 41</item>
    <item name="item_email">[email protected]</item>
    <item name="item_website">www.website.com</item>
</string-array>

<string-array name="address_list_items">
    <item name="item_title">Address</item>
    <item name="item_address">xxxxxx\nxxxxxxxxxxx\nxxxxxxxxxx\nxxxxxxx</item>
    <item name="item_other">PDF</item>
</string-array>

That should be it! Good luck!

Upvotes: 1

Related Questions