Introduction à cette section :
Comme l'un des problèmes classiques de ListView, si vous avez déjà essayé de personnaliser un élément de ListView avec une CheckBox dessus, alors lorsque le nombre d'éléments dépasse une page, ce problème se produira. Ci-dessous, nous allons analyser la cause de ce problème et comment le résoudre !
1. Causes du problème :
Ceci est un diagramme trouvé en ligne sur le mécanisme d'appel de la méthode getView de ListView.

Dans la figure ci-dessus, il y a uneRecyclerchose. Normalement, les Items visibles sur notre ListView sont en mémoire, tandis que les autres Items sont placés dans ce Recycler. Lors du premier chargement des items, le convertView de la page actuelle est NULL. Lorsqu'il est fait défiler hors de l'écran, c'est le cas à ce moment-là, donc un nouvel item réutilise ce ConvertViewConvertViewNous pouvons écrire un exemple simple et suivre le log. Ci-dessous se trouvent quelques diagrammes de log après exécution !

Comme on peut le voir sur la figure, à partir de Position 12, ConvertView n'est plus null. Quant à ce que cela représente exactement ici, je ne le sais pas non plus ; il semble que nous devions aller dans le code source... Nous avons juste besoin de savoir que ConvertView est mis en cache ici. C'est pour cette raison que la CheckBox devient désalignée. Donc la première solution est de ne pas réutiliser ce ConvertView, ou de définir ce ConvertView à null à chaque fois dans getView. Cependant, si le nombre d'Items à afficher est énorme, cette approche semblera très lourde. En développement réel, nous utilisons généralement la solution suivante :Trouvez quelque chose pour enregistrer l'état actuel de la CheckBox de l'Item, faites un test lors de l'initialisation, et définissez s'il est sélectionné !
2. Exemples de solutions :
Eh bien, il existe de nombreuses façons de stocker ce CheckBox. Vous pouvez le placer dans un HashMap<Integer, Boolean>, et à chaque fois lors de l'initialisation, récupérer la valeur booléenne correspondante en fonction de la position, puis définir l'état du CheckBox. Mon approche, cependant, consiste à ajouter une valeur booléenne à la classe d'entité pour le jugement. Voici le code extrait de l'un de mes projets. Le code est assez simple ; je pense que vous le comprendrez instantanément après l'avoir lu~
Classe d'entité :Person.java:
public class Person implements Serializable{
private String name;
private String number;
private boolean checkStatus;
public Person(String name, String number) {
super();
this.name = name;
this.number = number;
this.checkStatus = false;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public boolean getCheckStatus() {
return checkStatus;
}
public void setCheckStatus(boolean checkStatus) {
this.checkStatus = checkStatus;
}
}
La classe Adapter implémentée :ContactListAdapter.java:
public class ContactListAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener{
private List<Person> mData;
private Context mContext;
public ContactListAdapter(List<Person> data, Context context) {
mData = data;
mContext = context;
}
// 定义一个刷新数据的方法
public void changeData(List<Person> data) {
mData = data;
notifyDataSetChanged();
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Person getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int index = position;
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item_contact, parent, false);
viewHolder = new ViewHolder();
viewHolder.ly = (RelativeLayout) convertView
.findViewById(R.id.lyContactListItem);
viewHolder.txtName = (TextView) convertView
.findViewById(R.id.txtName);
viewHolder.txtNumber = (TextView) convertView
.findViewById(R.id.txtNumber);
viewHolder.cbxStatus = (CheckBox) convertView
.findViewById(R.id.cbxStatus);
convertView.setTag(viewHolder);
viewHolder.cbxStatus.setTag(index);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.cbxStatus.setOnCheckedChangeListener(this);
viewHolder.cbxStatus.setChecked(mData.get(position).getcheckStatus());
viewHolder.txtName.setText(mData.get(index).getName());
viewHolder.txtNumber.setText(mData.get(index).getNumber());
return convertView;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int index = (int)buttonView.getTag();
if (isChecked)
mData.get(index).setCheckStatus(true);
else
mData.get(index).setCheckStatus(false);
}
private class ViewHolder {
RelativeLayout ly;
TextView txtName;
TextView txtNumber;
CheckBox cbxStatus;
}
}
Héhé, c'est très simple. Aussi, n'oubliez pas un point :La méthode d'écoute du CheckBox doit être ajoutée avant le code qui initialise l'état du CheckBox~
Introduction à cette section :
Bien, dans cette section nous avons expliqué un problème classique de ListView : résoudre le désalignement des CheckBox dans ListView. Il vous suffit simplement d'ajouter une valeur pour enregistrer l'état de sélection du CheckBox, puis, lors de la redéfinition de l'événement de clic du CheckBox, effectuer d'abord une vérification~ Merci~