Droidman
Droidman

Reputation: 11608

how to show a certain number of child groups

I have an ExpandableListView, the count of child groups can vary since they are dynamically created. I need the first 3 child groups to be always expanded by default. When the user clicks on a main group, the rest of the child groups will be expanded (I attached a figure illustrating the default state of an ExpandableListView I need to achieve). I haven't found any methods for the ExpandableListView which would allow to achieve that.

Any suggestions?

enter image description here

Upvotes: 0

Views: 598

Answers (3)

Simas
Simas

Reputation: 44118

I've had a similar idea as @Pr38y but didn't find the time to code it (until now). Still kudos to him/her. This ExpandableList prevents full collapse of a group. It's done by only switching the childCount for each group, based on a boolean (isGroupExpanded).

Demo myClass:

public class myClass {
    int id;
    String name;
    public myClass(int id, String str) {
        this.id = id;
        this.name = str;
    }
}

Activity (sorry for the humongous HashMap initialization):

package com.example.explvhack;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Simon on 2014 Jul 8.
 */

public class MainActivity extends Activity {

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

        ExpandableListView expList = (ExpandableListView) findViewById(R.id.expList);

        // Create the adapter with 3 groups
        final List<String> groups = new ArrayList<String>() {{add("Group1"); add("Group2"); add("Group3");}};
        final ExpLvAdapter expAdapter = new ExpLvAdapter(getBaseContext(), groups);

        // If group is not "expanded" it displays 3 children, else displays all
        // This listener, forces it to toggle between fake expanded and collapse states
        expList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView dad, View v, int grpPosition, long id) {
                expAdapter.isGroupExpanded[grpPosition] = !expAdapter.isGroupExpanded[grpPosition];
                expAdapter.notifyDataSetChanged();

                return true;
            }
        });

        expList.setAdapter(expAdapter);

        // Populate the groups
        HashMap<String, List<myClass>> newData =
                new HashMap<String, List<myClass>>() {
                    {
                        put(groups.get(0), new ArrayList<myClass>() {
                            {
                                add(new myClass(0, "Grp1Child1"));
                                add(new myClass(1, "Grp1Child2"));
                                add(new myClass(2, "Grp1Child3"));
                                add(new myClass(3, "Grp1Child4"));
                                add(new myClass(4, "Grp1Child5"));
                                add(new myClass(5, "Grp1Child6"));
                                add(new myClass(6, "Grp1Child7"));
                                add(new myClass(7, "Grp1Child8"));
                            }
                        });
                        put(groups.get(1), new ArrayList<myClass>() {
                            {
                                add(new myClass(0, "Grp2Child1"));
                                add(new myClass(1, "Grp2Child2"));
                                add(new myClass(2, "Grp2Child3"));
                                add(new myClass(3, "Grp2Child4"));
                            }
                        });
                        put(groups.get(2), new ArrayList<myClass>() {
                            {
                                add(new myClass(0, "Grp3Child1"));
                                add(new myClass(1, "Grp3Child2"));
                                add(new myClass(2, "Grp3Child3"));
                            }
                        });

                    }
                };
        expAdapter.putAll(newData);
        expAdapter.notifyDataSetChanged();

        // Keep the groups opened
        expList.expandGroup(0);
        expList.expandGroup(1);
        expList.expandGroup(2);
    }

}

And the custom adapter:

package com.example.explvhack;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.HashMap;
import java.util.List;

/**
 * Created by Simon on 2014 Jul 8.
 */

public class ExpLvAdapter extends BaseExpandableListAdapter {
    private Context context;
    private List<String> groups;
    private HashMap<String, List<myClass>> children = new HashMap<String, List<myClass>>();
    public boolean[] isGroupExpanded = new boolean[] {false, false, false};

    public ExpLvAdapter(Context context, final List<String> groups) {
        this.context = context;
        this.groups = groups;
    }

    public void putAll(HashMap<String, List<myClass>> newData) {
        children.putAll(newData);
    }

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

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

    @Override
    public View getChildView(int groupPosition, int childPosition,
                             boolean isLastChild, View convertView, ViewGroup parent) {
        if (convertView == null)
            convertView = new TextView(context);

        // (Re)Use the convertView
        TextView textView = (TextView) convertView;
        textView.setPadding(60, 0, 30, 0);
        textView.setText(children.get(groups.get(groupPosition)).get(childPosition).name);

        return convertView;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        int childrenCount = (children.size() == 0) ? 0 : children.get(groups.get(groupPosition)).size();

        if (isGroupExpanded[groupPosition])
            return childrenCount;
        else
            return Math.min(3, childrenCount);
    }

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

    @Override
    public int getGroupCount() {
        return 3;
    }

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

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
                             View convertView, ViewGroup parent) {
        if (convertView == null)
            convertView = new TextView(context);

        // (Re)Use the convertView
        TextView textView = (TextView) convertView;
        textView.setText(groups.get(groupPosition));

        return textView;
    }

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

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

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

    }

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

By the way I also removed the group indicator so there would be no confusion if it's open or not. I used android:groupIndicator="@null" in my <ExpandableListView .../>

Upvotes: 2

Pr38y
Pr38y

Reputation: 1565

Using normal linearlayout with listview could be a better approach. on click of title in the linearlayout you can fully pouplate the list of the listview adapter and call notifyDataSetChanged and on next tap you can reduce the list to 3 elements.

Using ExpandableListView for the first time you can return 3 from getChildCount() and next time the size of the entire list. You can achieve this effect by either from onGroupExpandListener or from the adapter itself.

Upvotes: 1

j__m
j__m

Reputation: 9625

duplicate your special child items as top-level items, styled to appear like child items. then when a top-level item is expanded for real, set the height of the fake child items to zero.

Upvotes: 2

Related Questions