2010-10-12 16 views
5

Ich habe ein Android ListView, deren Artikel ein Kontrollkästchen haben.CheckBox ändert Wert zweimal

Das Kontrollkästchen ist standardmäßig aktiviert. Einmal deaktiviert, sollte es aus der Liste entfernt werden.

Das Problem ist, dass onCheckedChanged zweimal gebrannt wird: wenn ich das Kontrollkästchen tippen, um es zu deaktivieren (mit isCheckedfalse) und nachdem ich den Artikel entfernen (mit isCheckedtrue).

Dieser der entsprechende Code meiner ArrayAdapter:

public View getView(final int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.item, parent, false); 
     holder = new ViewHolder(); 
     holder.check = (CheckBox) convertView.findViewById(R.id.check); 
     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 
    final Object item = this.getItem(position); 
    holder.check.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      if (!isChecked) { 
       remove(item); // This somehow calls onCheckedChanged again 
      } 
     } 
    }); 
    return convertView; 
} 

Was mache ich falsch?

+0

Was macht die 'remove()' Methode, da dies keine Methode auf 'ListAdapter' ist? – CommonsWare

+0

Ich verwende einen ArrayAdapter. Gemäß dem Android-Quellcode entfernt die remove-Methode das Element aus dem Array und benachrichtigt, dass die Daten geändert wurden. – hpique

Antwort

0

Ich stoße auf das gleiche Problem.

Nach einigen Recherchen fand ich heraus, dass es in der RadioGroup ein ähnliches Verhalten für den setCheckChangeListener gibt.

Tagging vermasselt Dinge, scheint wie ein Fehler.

Meine Problemumgehung war das Setzen des Tags auf Null am Ende des Listeners Es funktionierte für mich.

private OnCheckedChangeListener checkBoxitemClickListener = new OnCheckedChangeListener() { 

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 


     if(isChecked) 
     {    
      //do smth 
     }else 
     { 
      //do smth 
     } 

     buttonView.setTag(null);       
    } 
}; 

Wenn Sie Ihre Listview nach aktualisieren, vergessen Sie nicht „notifyDataSetChanged“ auf Ihrem Adapter anzurufen.

Prost

5

ich das gleiche Problem gestoßen, wie es scheint dies zweimal Ausführung onCheckChanged Methode ein Android-Bug zu sein.

Meine Lösung: onClickListener statt onCheckedChangedListener implementieren.

Etwas wie folgt aus:

private final class CheckUpdateListener implements OnClickListener { 

    private Group parent; 
    private boolean isChecked; 

    private CheckUpdateListener(Group parent) { 

     this.parent = parent; 

    } 

    @Override 
    public void onClick(View box) { 
     this.isChecked = !parent.isChecked(); 

     parent.setChecked(isChecked); 

     notifyDataSetChanged(); 

    } 

} 
+0

Ja, ich denke, onCheckedChange zu hören ist zu viel und in den meisten Fällen nicht das Richtige. Das grundlegende Problem für mich war jedoch, die richtige Perspektive zu bekommen, dh dass die Ansicht nicht mit dem Datenobjekt identisch ist, das betrachtet wird. – rwst

2

hatte ich ein ähnliches Problem und es nur richtig gelöst, ohne zu vermeiden, dass das beabsichtigte OnCheckedChangeListener verwenden.

Problem-Code

holder.someCheckBox.setChecked(false); 
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     ... 
    } 
}); 

Hinweis habe ich den Prüfstatus vor ich den Hörer gesetzt, diese den Hörer von Brennen auf Schöpfung zu verhindern war.

Aber das Listener-Ereignis hat das On-check-Ereignis genau zweimal ausgelöst, nachdem der Adapter neu erstellt werden musste oder notifyDataSetChanged verwendet wurde.

Lösung

Löschen Sie den Hörer vor das Kontrollzustand versetzt, auch hier während der Erstellung.

holder.someCheckBox.setOnCheckedChangeListener(null); 
holder.someCheckBox.setChecked(false); 
holder.someCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     ... 
    } 
}); 

Jetzt werden alle verbleibenden Listener nicht ausgelöst, wenn der Anfangswert des Kontrollkästchens festgelegt wird.