0

I am new to Android and I'm struggling to do the following using ExpandableListView.

I want to have 3 groups - 'online', 'offline' and 'away'. The groups will contain children custom objects (Contacts) which will be loaded from the Internet. The objects will only be in one group at a time (though this might change later on).

I have attempted this myself without asking for help and I will paste the code - it gets me to showing the listview with the right groups but the children are in all groups.

In the code, the Contact items are currently just in a vector in another class.

I would really appreciate some help with this as I am truly stuck.

public class MyTreeAdaptor extends BaseExpandableListAdapter{
@Override
public boolean areAllItemsEnabled()
{
    return true;
}


private Context context;
private ArrayList<String> groups;
private ArrayList<ArrayList<Contact>> children;
public MyTreeAdaptor(Context context, ArrayList<String> groups,
        ArrayList<ArrayList<Contact>> children) {
    this.context = context;
    this.groups = groups;
    this.children = children;
}


/**
 * A general add method, that allows you to add a Contact to this list
 * 
 * Depending on if the category opf the Contact is present or not,
 * the corresponding item will either be added to an existing group if it 
 * exists, else the group will be created and then the item will be added
 * @param Contact
 */
public void addItem(Contact aContact) {
    try {
        Log.e("additem", ""+aContact.show);
        if (!groups.contains(aContact.show)) {
            groups.add(aContact.show);
        }
        int index = groups.indexOf(aContact.show);
        if (children.size() < index + 1) {
            children.add(new ArrayList<Contact>());
        }
        children.get(index).add(aContact);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        Log.e("additem error", " "+e);
    }
}


@Override
public Object getChild(int groupPosition, int childPosition) {
    return children.get(groupPosition).get(childPosition);
}


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

// Return a child view. You can load your custom layout here.
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
        View convertView, ViewGroup parent) {
    try {
        Contact contact = (Contact) getChild(groupPosition, childPosition);
        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.treeview, null);
        }
        TextView tv = (TextView) convertView.findViewById(R.id.text1);
        try {
            tv.setText("   " + contact.name);
            tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        // Depending upon the child type, set the imageTextView01

        /*if (Contact instanceof Car) {
            tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.car, 0, 0, 0);
        } else if (Contact instanceof Bus) {
            tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.bus, 0, 0, 0);
        } else if (Contact instanceof Bike) {
            tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.bike, 0, 0, 0);
        }*/
        return convertView;
    } catch (Exception e) {
        Log.e("error thr", " "+e);
        e.printStackTrace();
        return null;
    }
}


@Override
public int getChildrenCount(int groupPosition) {
    try
    {
    return children.get(groupPosition).size();
    }
    catch(Exception hh)
    {
        return 0;

    }
}


@Override
public Object getGroup(int groupPosition) {
    return groups.get(groupPosition);
}


@Override
public int getGroupCount() {
    return groups.size();
}


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


// Return a group view. You can load your custom layout here.
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
        ViewGroup parent) {
    try {
        Log.e(groupPosition+"groups size is", " "+groups.size());
        String group;
        if(groups.size() > 0) 
        {
            group = (String) getGroup(groupPosition);
        }
        else
        {
            group = "null";//(String) getGroup(groupPosition);
        }

        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.treeview, null);
        }
        TextView tv = (TextView) convertView.findViewById(R.id.text1);
        try {
            tv.setText(group);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return convertView;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
}


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


@Override
public boolean isChildSelectable(int arg0, int arg1) {
    return true;
}
}
Kevin Bedell
  • 13,254
  • 10
  • 78
  • 114
  • are the child views structurally same or different? – Jeshurun Jun 26 '12 at 19:24
  • same I think - I just have 2 layout files treeitem.xml containing a linerlayout and treeview.xml which also has a linearlayout but also containing a imageview. forgive me if i have implemented this wrong - just a newbie. – Arial Buckley Jun 26 '12 at 19:28

1 Answers1

0

If you have two different types of child views, you will have to implement these methods in your Adapter:

@Override
public int getChildTypeCount() {
    return 2;
}

@Override
public int getChildType(int groupPosition, int childPosition) {
    return groupPosition == 4 ? 1 : 0;
}

Then make the following changes to the getChildView method:

LayoutInflater layoutInflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = convertView;
if(v == null) {
    if (groupPosition == 4) {
        v = layoutInflater.inflate(R.layout.treeitem, null);
    } else {
        v = layoutInflater.inflate(R.layout.treeview, null);
}


TextView tt = null;
if (groupPosition != 4) {
        tt = (TextView) v.findViewById(R.id.text1);
// rest of the method

To understand how this works, spend some time watching this video and also this answer on SO. The concepts explained for ListView equally apply to an ExpandableListView as well.

Community
  • 1
  • 1
Jeshurun
  • 22,940
  • 6
  • 79
  • 92
  • I think i might have been misunderstood - all i actually want to achieve is a expandable list which has 3 headers and various contacts will be grouped under these headers (online, away, offline) but my childs will be displayed consistently. Any quick way to insert a vector of custom objects into various groups of my list depending on say their online status? – Arial Buckley Jun 26 '12 at 19:51
  • my confusion is how does arraylist (children) get linked to the groups? – Arial Buckley Jun 26 '12 at 20:49
  • I'm guessing you will have to use a Map with the groups as keys and a List of children for each key. Like `Map>`. – Jeshurun Jun 26 '12 at 21:13
  • I have just edited my class code from first post, I'm getting close and appreciate your help. The code now implements like this public MyTreeAdaptor(Context context, ArrayList groups, ArrayList> children) and this is very close, my problem is when i prepopulate Groups (chats, online, away) I have a problem with addItem because its getting indexoutofboundes due to children.get(index).add(aContact); - I cannot see how to allow different number of groups to different numbers of children. – Arial Buckley Jun 26 '12 at 22:14