2

Dans ma liste ExpandableListView, j'ai une liste de planètes en tant que groupes, et je veux qu'un de ces groupes disparaisse lorsqu'un CheckBox de l'activité principale est cochée. Malheureusement, cela se produit:Comment masquer un groupe spécifique dans ExpandableListView à l'aide de CheckBox

Filter Unchecked

Filter Checked

Voici le code qui affecte la visibilité de la vue. Comme vous pouvez le voir, je mets 1 comme int pour 'groupPosition' donc la vue qui est cachée devrait être Saturne et non Jupiter et le résultat est le même quelle que soit la valeur de 'groupPosition'.

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(); 
      } 
     } 
    }); 

Merci d'avance.

EDIT: Cela a fonctionné Kris, merci. Maintenant, comment puis-je appliquer efficacement ce filtre à l'un des childViews ici? (Les enfants sont HashMap) par exemple.

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(); 
} 

J'essaie de filtrer une chaîne en fonction de sa position dans la liste <> ici et le remettre dans son propre « montré » HashMap> appelé planet_child_shown. Cela jette toujours un NullPointer cependant, et des points à ma méthode getChildrenCount() que je Modelé sur votre getGroupCount():

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

Répondre

1

Avec ListView s, vous éviterez beaucoup de problèmes si vous restez strictement MVC:

  • Le contrôleur (ie onCheckedChanged) met à jour le modèle. Le modèle est converti en affichage par getView (dans votre cas, getGroupView).

Ce que vous faites est d'essayer de mettre à jour la vue directement depuis le contrôleur. Cela causera toujours des problèmes.

Vous devez faire quelque chose comme ceci:

classe Model (édité):

public class Planet { 

    public String name; 

    public boolean filtered; 

    private List<String> mChildren; 

    private List<Boolean> mChildrenFiltered; 

    private List<String> mChildrenShown; 

    public Planet(String name, List<String> children) { 
     this.name = name; 
     mChildren = children; 
     mChildrenFiltered = new ArrayList<>(); 
     for (String child : children) { 
      mChildrenFiltered.add(false); 
     } 
     mChildrenShown = new ArrayList<>(children); 
    } 

    public int getChildrenCount() { 
     return mChildrenShown == null ? 0 : mChildrenShown.size(); 
    } 

    public String getChild(int position) { 
     return mChildrenShown.get(i); 
    } 

    public void filter(String child, boolean filter) { 

     mChildrenShown.clear(); 
     for (int i = 0; i < mChildren.size(); i++) { 

      if (mChildren.get(i).equals(child)) { 
       mChildrenFiltered.set(i, filter); 
      } 

      if (! mChildrenFiltered.get(i)) { 
       mChildrenShown.add(mChildren.get(i)); 
      } 
     } 

    } 
} 

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); 
     } 
    }); 

Maintenant dans votre adaptateur, vous aurez deux listes: la liste de toutes les planètes et la liste des planètes qui apparaîtront dans votre ExpandableListView. Cocher la case ne changera que la liste des planètes affichées, ce que vous utiliserez lors de la création de la vue du groupe.

MyAdapter.java: (Editied, a ajouté une méthode de filtre enfant)

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); 
    } 

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

     Planet planet = (Planet) getGroup(groupPosition); 

     // TODO create the view 
     return null; 
    } 

    @Override 
    public int getChildrenCount(int groupPosition) { 
     return mPlanetsShown.get(groupPosition).getChildrenCount(); 
    } 

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

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

     String child = mPlanetsShown.get(groupPosition).getChild(childPosition); 

     // TODO create the view 
     return null; 
    } 

    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(); 
    } 

    public void filter(String planetName, String childName, boolean filter) { 

     for (Planet planet : mPlanets) { 
      if (planet.name.equals(planetName)) { 
       planet.filter(childName, filter); 
      } 
     } 

     notifyDataSetChanged(); 
    } 


    // TODO some code left out here 
} 
+0

@Andrej si vous voulez bien mettre à jour votre question avec votre code d'adaptateur et votre code modèle (Planet), je vais mettre à jour ma réponse. Cela revient toujours à MVC. Le modèle doit contenir l'état de la liste extensible à un moment donné. L'adaptateur devrait avoir des méthodes pour changer le modèle où 'notifyDataSetChanged()' est appelé à la toute fin. –

+0

Ouais j'ai laissé un commentaire accidentel ici, mais ma question a été éditée, merci :) –

+0

Mis à jour ma réponse. En bref, l'adaptateur est responsable du suivi des groupes filtrés, et le modèle de groupe (Planet) a été chargé de suivre les enfants filtrés. –