Andrej Butić Andrej Butić - 6 months ago 43
Java Question

How do I hide specific Group in ExpandableListView using CheckBox

In my ExpandableListView I have a list of planets as groups, and I want one of those groups to disappear when a CheckBox from the main activity is checked.
Unfortunately, this happens:

Filter Unchecked

Filter Checked

Here is the code that affects the view visibility. As you can see, i put 1 as the int for 'groupPosition' so the view that gets hidden should be Saturn and not Jupiter and the result is the same no matter what the value of 'groupPosition' is.

final MyAdapter myAdapter = new MyAdapter(this, headings, childList);
expandableListView.setAdapter(myAdapter);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(checkBox.isChecked()){
myAdapter.getGroupView(1,false,findViewById(R.id.planet), expandableListView).setVisibility(View.GONE);
myAdapter.notifyDataSetChanged();
}
if(!checkBox.isChecked()){
myAdapter.getGroupView(1,false,findViewById(R.id.planet), expandableListView).setVisibility(View.VISIBLE);
myAdapter.notifyDataSetChanged();
}
}
});


Thank you in advance.

EDIT: That worked Kris, thank you. Now, how can I effectively apply this filter to one of the childViews here? (the children are HashMap) eg.

public void childFilter(int position, boolean filterCheck) {
planet_child_shown.clear();
String str;
if(!filterCheck) {

for (List<String> l : planet_child.values()) {

for (int i = 0; i < l.size(); i++) {
if (i!=position) {
str = l.get(i);
l.add(str);
}
}
}
}
notifyDataSetChanged();
}


I am trying to filter out a String depending on its position in the List<> here and put it back into its own "shown" HashMap> called planet_child_shown. This always throws out a nullPointer however, and points to my getChildrenCount() method which i modelled after your getGroupCount():

public int getChildrenCount(int groupPosition) {
return planet_child_shown == null ? 0 : planet_child_shown.get(mPlanetShown.get(groupPosition).name)
.size();
}

Answer

With ListViews, you will avoid a lot of problems if you stay strict MVC:

  • Controller (i.e. onCheckedChanged) updates the Model.

  • Model is converted to View by getView (in your case, getGroupView).

What you are doing is trying to update the view directly from the controller. This will always cause problems.

You need to do something like this:

Model class:

public class Planet {

    public String name;

    public boolean filtered;

    // TODO all the properties that would show up in the child views
}

Controller:

    final MyAdapter myAdapter = new MyAdapter(this, headings, childList);
    expandableListView.setAdapter(myAdapter);
    checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            myAdapter.filter("Saturn", isChecked);
        }
    });

Now in your adapter, you will have two lists: the list of all the planets and the list of the planets that will show up in your ExpandableListView. Checking the checkbox will change only the list of planets that are shown, which is what you will use when creating the group view.

MyAdapter.java:

public class MyAdapter extends BaseExpandableListAdapter {

    private List<Planet> mPlanets;

    private List<Planet> mPlanetsShown;

    public MyAdapter(List<Planet> planets) {
        mPlanets = planets;
        mPlanetsShown = new ArrayList<>(mPlanets);
    }

    @Override
    public int getGroupCount() {
        return mPlanetsShown == null ? 0 : mPlanetsShown.size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mPlanetsShown == null ? null : mPlanetsShown.get(groupPosition);
    }

    public void filter(String planetName, boolean filter) {

        mPlanetsShown.clear();
        for (Planet planet : mPlanets) {

            // if this is the planet we are changing, set the flag
            if (planet.name.equals(planetName)) {
                planet.filtered = filter;
            }

            // whether this is the planet we are changing or not,
            // add this to planets shown if the flag is not set
            if (! planet.filtered) {
                mPlanetsShown.add(planet);
            }
        }

        notifyDataSetChanged();
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        Planet planet = (Planet) getGroup(groupPosition);

        // TODO create the view
        return null;
    }

    // TODO lots of code left out here
}