Estava eu dando uma brincada com Android implementando uma Expandable ListView com CheckBox,
quando me deparei com uma situação chata: Ao marcar alguns checkboxs, e usar o scroll da
app, percebi que alguns itens que não tinha marcado, misteriosamente apareciam marcados, e os
itens que tinha marcado antes dos scrooling, já não esatavam mais marcados.
|
Antes e depois de utilizar o scroll |
Pois bem, após algumas pesquisas vi que esse problema estava acontecendo com varias pessoas, porém
não achei nenhuma solução funcionando, e resolvi disponibilizar por aqui.
Primeiramente, os check box estavam mudando de estado por causa do ListView Recycle no meu Adapter,
que resolvi armazenando o estado em uma coleção no onClick... e no momento antes do retorno do metodo getChildView(...)
eu veficido se um determinado identificador existe.
expandable.xml
list_item_group.xml
list_item_child.xml
ChildEntity.java
package com.blogspot.receitastecnologicas;
import java.math.BigDecimal;
import java.text.ParseException;
public class ChildEntity {
private Integer id;
private String descricao;
private BigDecimal valor;
public ChildEntity() {
// TODO Auto-generated constructor stub
}
public ChildEntity(int id, String descr, BigDecimal valor) {
this.id = id;
this.descricao = descr;
this.valor = valor;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public BigDecimal getValor() {
return valor;
}
public void setValor(BigDecimal valor) {
this.valor = valor;
}
public String getValorFormatado() throws ParseException {
// TODO Auto-generated method stub
return this.getValor().toString();
}
}
GrupoEntity.java
package com.blogspot.receitastecnologicas;
import java.util.List;
public class GrupoEntity {
private Integer id;
private String descricao;
private String tipo;
private List listChild;
public GrupoEntity() {
}
public GrupoEntity(Integer id, String descricao, String tipo) {
this.id = id;
this.descricao = descricao;
this.tipo = tipo;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public String getTipo() {
return tipo;
}
public void setTipo(String tipo) {
this.tipo = tipo;
}
public List getListChild() {
return listChild;
}
public void setListChild(List listChild) {
this.listChild = listChild;
}
@Override
public String toString() {
return this.getId() + " - " + this.getDescricao();
}
}
MainActivity.java
package com.blogspot.receitastecnologicas;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ExpandableListView;
import com.blogspot.receitastecnologicas.R;
public class MainActivity extends Activity {
ExpandableListView explistView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.expandable);
explistView = (ExpandableListView) findViewById(R.id.list_expandable);
List listgrupo = new ArrayList();
GrupoEntity grupo = new GrupoEntity(1, "Street Fighter", "D");
List child = new ArrayList();
child.add(new ChildEntity(1, "Ryu", new BigDecimal(10)));
child.add(new ChildEntity(2, "Blanka", new BigDecimal(20)));
child.add(new ChildEntity(3, "Vega", new BigDecimal(30)));
grupo.setListChild(child);
listgrupo.add(grupo);
GrupoEntity grupo1 = new GrupoEntity(2, "Mortal Kombat", "D");
List child1 = new ArrayList();
child1.add(new ChildEntity(4, "Sub Zero", new BigDecimal(10)));
child1.add(new ChildEntity(5, "Scorpion", new BigDecimal(20)));
child1.add(new ChildEntity(6, "Rayden", new BigDecimal(30)));
grupo1.setListChild(child1);
listgrupo.add(grupo1);
GrupoEntity grupo2 = new GrupoEntity(3, "Oh my Dog!", "D");
List child2 = new ArrayList();
child2.add(new ChildEntity(7, "Allejo", new BigDecimal(10)));
child2.add(new ChildEntity(8, "Chuck Norris", new BigDecimal(20)));
child2.add(new ChildEntity(9, "Jeremias", new BigDecimal(30)));
grupo2.setListChild(child2);
listgrupo.add(grupo2);
// sets the adapter that provides data to the list.
explistView.setAdapter(new ExpandableAdapter(MainActivity.this,
listgrupo));
}
}
ExpandableAdapter.java
package com.blogspot.receitastecnologicas;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.CheckBox;
import android.widget.TextView;
import com.blogspot.receitastecnologicas.R;
public class ExpandableAdapter extends BaseExpandableListAdapter {
private Context ctx;
private List lista;
private Map childSelected = new HashMap();
public ExpandableAdapter(Context ctx, List lista) {
super();
this.ctx = ctx;
this.lista = lista;
}
// interface
public Object getChild(int groupPosition, int childPosition) {
return lista.get(groupPosition).getListChild().get(childPosition);
}
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final ViewChildHolder holder;
final ChildEntity child = lista.get(groupPosition).getListChild()
.get(childPosition);
if (convertView == null) {
convertView = LayoutInflater.from(ctx).inflate(
R.layout.list_item_child, null);// carregando layout
holder = new ViewChildHolder();
holder.id = (TextView) convertView.findViewById(R.id.txtid);
holder.txtValor = (TextView) convertView
.findViewById(R.id.txtValorTitulo);
holder.check = (CheckBox) convertView.findViewById(R.id.chkItem);
holder.check.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox chk = (CheckBox) v;
Log.d("Check", "Selecionado " + holder.check.getText()
+ " Holder:" + holder);
if (chk.isChecked()) {
if (!childSelected.containsKey(holder.id.getText()))
childSelected.put(holder.id.getText().toString(),
true);
} else {
if (childSelected.containsKey(holder.id.getText()))
childSelected.remove(holder.id.getText());
}
holder.check.setChecked(chk.isChecked());
}
});
convertView.setTag(holder);
} else {
holder = (ViewChildHolder) convertView.getTag();
}
holder.check.setText(child.getDescricao());
holder.txtValor.setText(child.getValor().toString());
holder.id.setText(child.getId().toString());
holder.check.setChecked(childSelected.containsKey(holder.id.getText()));
return convertView;
}
static class ViewChildHolder {
TextView id;
TextView txtValor;
CheckBox check;
}
public int getChildrenCount(int groupPosition) {
return lista.get(groupPosition).getListChild().size();
}
public Object getGroup(int groupPosition) {
return lista.get(groupPosition);
}
public int getGroupCount() {
return lista.size();
}
public long getGroupId(int groupPosition) {
return groupPosition;
}
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
ViewGroupHolder holder;
GrupoEntity grupo = lista.get(groupPosition);
if (convertView == null) {
convertView = LayoutInflater.from(ctx).inflate(
R.layout.list_item_group, null);// carregando layout
holder = new ViewGroupHolder();
holder.txtDescricao = (TextView) convertView
.findViewById(R.id.txt_item_group);
convertView.setTag(holder);
} else {
holder = (ViewGroupHolder) convertView.getTag();
}
holder.txtDescricao.setText(grupo.getDescricao());
return convertView;
}
static class ViewGroupHolder {
TextView txtDescricao;
}
public boolean hasStableIds() {
return true;
}
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
http://developer.android.com/reference/android/widget/ExpandableListView.html