Créer une ListView avec des contrôles CheckBox et gérer les événements sur ces derniers

Silvera David

L'application que je vous propose est assez classique et simple. Il s'agit de créer une liste comportant des checkbox. Au clic d'une checkbox, ceci va faire changer la couleur de fond du bloc de celle-ci. Attention: suite à quelque bogue sur ce tutoriel, je vous informe que ce tutoriel fonctionne seulement si la hauteur de la ListView ne dépasse pas la hauteur de l'écran (il ne faut pas avoir de scroll). Une solution est de créer une pagination pour passer à la suite de la liste.
Commentez

- Titre : Créer une ListView avec des contrôles CheckBox et gérer les événements sur ces derniers

- Auteur : Silvera David

- Parution : 6 juillet 2011

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2011 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Création de l'application

- III. Les vues

- IV. Les paramètres

- V. L'activité

- VI. L'adaptateur

- VII. Conclusion

- VIII. Remerciements

I - Introduction

Voici des captures d'écran de l'application :

Les technologies utilisées dans ce tutoriel sont :
- listView ;
- listActivity ;
- événement sur checkbox ;
- adaptateur.

II - Création de l'application

Pour cela nous allons commencer par créer une application :

III - Les vues

Commençons par les vues.
La première est le main.xml. Elle comprend la listView (la liste). Sachant que nous allons utiliser une ListActivity par la suite, l'identifiant de la listView sera @android:id/list. Ce qui permettra à l'activité de reconnaitre automatiquement la liste.
Voici le code de la vue qui est assez simple :

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

<ListView android:id="@android:id/list" android:layout_width="fill_parent"
android:layout_height="fill_parent" />

</LinearLayout>

La deuxième vue, nommée list_detail.xml, correspond au contenu de chaque ligne de la liste. Dans notre exemple, nous avons en tout quatre champs texte (deux libellés et deux champs modifiables) et une checkbox. Les champs texte sont placés dans des tableaux afin de pouvoir les intégrer correctement avec la checkbox. Mais là, libre à vous de placer vos champs où vous voulez !
Pour la checkbox, nous définissons la fonction qui permettra de récupérer l'événement dans l'activité comme ceci android:onClick="MyHandler". L'identifiant de la checkbox est check, celle du champ modifiable contenant le nom est nom et celui du prénom est prenom.
Pour une raison ergonomique, nous choisissons de colorer une partie du bloc. Cette partie est celle définie par l'identifiant blocCheck.
Voici le code :

list_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="wrap_content">

<!-- Tableau permettant d'afficher tout le contenu d'un bloc -->
<TableLayout android:id="@+id/blocCheck"
android:background="@color/blue"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginTop="25px"
android:layout_marginBottom="25px">

<!-- La première ligne affiche deux libellés côte à côte (le nom et sa valeur) -->
<TableRow android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="4sp"
android:paddingBottom="4sp">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="20sp"
android:layout_weight="1"
android:layout_gravity="center_vertical">

<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/nom"
android:layout_gravity="left"
android:layout_marginRight="5sp" />
<TextView android:id="@+id/nom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_gravity="left" />
</LinearLayout>
</TableRow>

<!-- Cette ligne affiche les deux libellés du prénom et la checkbox -->
<TableRow android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="4sp"
android:baselineAligned="true">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="20sp"
android:layout_weight="1"
android:layout_gravity="center_vertical">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/prenom"
android:layout_gravity="left"
android:layout_marginRight="5sp" />
<TextView android:id="@+id/prenom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_gravity="left" />
</LinearLayout>
<CheckBox android:layout_height="wrap_content"
android:id="@+id/check"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10sp"
android:onClick="MyHandler"/>
</TableRow>
</TableLayout>
</LinearLayout>

Les vues sont créées.

IV - Les paramètres

Comme vous avez pu le remarquer, nous utilisons des variables définies dans d'autres fichiers xml afin de pouvoir internationaliser notre application si nous le souhaitons. Ainsi, nous avons un fichier string.xml comportant les différents libellés utilisés comme ceci :

string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, checkBoxListVue!</string>
<string name="app_name">CheckBox list</string>
<string name="nom">Nom : </string>
<string name="prenom">Prénom : </string>
</resources>

De même, nous allons utiliser des couleurs. Donc afin de pouvoir les modifier facilement et aussi de pouvoir les utiliser convenablement nous créons un fichier color.xml comme ceci :

color.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="blue">#3050A0</color>
<color name="green">#006600</color>
</resources>

V - L'activité

Écrivons maintenant l'activité.
Cette activité remplit ma liste et utilise un adaptateur redéfini par une classe écrite plus bas. Elle contient la fonction publique void MyHandler(View v) qui permet de récupérer l'événement du clic sur la checkbox (rappelez-vous, nous avons défini cette fonction dans la vue au niveau de la checkbox).
Voici le code commenté de l'activité :

checkBoxListVue.java

package com.developpez.vue;

import java.util.ArrayList;
import java.util.HashMap;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ListView;

public class checkBoxListVue extends ListActivity {
private ListView list;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//Récupération automatique de la liste (l'id de cette liste est nommé obligatoirement @android:id/list afin d'être détecté)
list = getListView();

// Création de la ArrayList qui nous permettra de remplir la listView
ArrayList<HashMap<String, String>> listItem = new ArrayList<HashMap<String, String>>();

// On déclare la HashMap qui contiendra les informations pour un item
HashMap<String, String> map;

map = new HashMap<String, String>();
map.put("nom", "Mouse");
map.put("prenom", "Mickey");
listItem.add(map);

map = new HashMap<String, String>();
map.put("nom", "Bunny");
map.put("prenom", "Bugs");
listItem.add(map);

//Utilisation de notre adaptateur qui se chargera de placer les valeurs de notre liste automatiquement et d'affecter un tag à nos checkbox

MyListAdapter mSchedule = new MyListAdapter(this.getBaseContext(), listItem,
R.layout.list_detail, new String[] { "nom", "prenom" }, new int[] {
R.id.nom, R.id.prenom });

// On attribue à notre listView l'adaptateur que l'on vient de créer
list.setAdapter(mSchedule);
}

//Fonction appelée au clic d'une des checkbox
public void MyHandler(View v) {
CheckBox cb = (CheckBox) v;
//on récupère la position à l'aide du tag défini dans la classe MyListAdapter
int position = Integer.parseInt(cb.getTag().toString());

// On récupère l'élément sur lequel on va changer la couleur
View o = list.getChildAt(position).findViewById(
R.id.blocCheck);

//On change la couleur
if (cb.isChecked()) {
o.setBackgroundResource(R.color.green);
} else {
o.setBackgroundResource(R.color.blue);
}
}
}

VI - L'adaptateur

Il ne reste plus qu'à définir la classe MyListAdaptater qui permettra surtout de définir un tag pour chaque checkbox. Ce tag correspond à la position du bloc (l'item) dans lequel est située la checkbox. Ceci est défini dans la fonction getView.
Voici le code commenté :

MyListAdaptater.java

package com.developpez.vue;

import java.util.List;
import java.util.Map;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.SimpleAdapter;

public class MyListAdapter extends SimpleAdapter
{
private LayoutInflater    mInflater;

public MyListAdapter (Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to)
{
super (context, data, resource, from, to);
mInflater = LayoutInflater.from (context);

}

@Override
public Object getItem (int position)
{
return super.getItem (position);
}

@Override
public View getView (int position, View convertView, ViewGroup parent)
{
//Ce test permet de ne pas reconstruire la vue si elle est déjà créée
if (convertView == null)
{
// On récupère les éléments de notre vue
convertView = mInflater.inflate (R.layout.list_detail, null);
// On récupère notre checkBox
CheckBox cb = (CheckBox) convertView.findViewById (R.id.check);
// On lui affecte un tag comportant la position de l'item afin de
// pouvoir le récupérer au clic de la checkbox
cb.setTag (position);
}
return super.getView (position, convertView, parent);
}

}

VII - Conclusion

Et voilà, votre application est terminée ! Vous pouvez désormais créer des listes et contrôler les événements liés aux éléments situés à l'intérieur de celle-ci.
Merci d'avoir suivi ce tutoriel et à bientôt ;)

VIII - Remerciements

Je tiens à remercier Feanorin, Viish, Jpelaho pour les améliorations apportées à ce tutoriel et ClaudeLELOUP pour la relecture.