Android Cours – Activités de type « liste »

Principe

On souhaite créer une activité de type « liste », afin d’afficher le contenu d’une liste. Le cas typique est d’afficher des résultats retournés par une requête sur la base de données. On peut aussi utiliser une liste pour créer un menu (type menu des préférences d’Android).

Le principe est que la mise en page des lignes de la liste sera elle-même définie dans un fichier de layout spécifique. Il existe des layouts par défaut (pour des cas simples, comme l’affichage de chaînes de caractères), mais on peut aussi définir soi-même un fichier de layout, ce qui permet de réellement mettre en forme ses lignes.

Pour ce faire on va créer une activité de type ListActivity, associée à un layout contenant un container de type ListView. Dans la méthode onCreate de l’activité on va associer notre liste à ce ListView par l’intermédiaire d’un adapteur, en indiquant à l’adapteur la référence du fichier de layout des ligne. Une classe adapteur permet d’adapter une classe contenant des données à ce qui est attendu dans une autre classe qui doit utiliser ces données.

Liste simple, avec l’adapteur par défaut

Si on dispose de la liste des données affichées sous la forme d’un tableau de type ArrayList<T> on va simplement utiliser l’adapteur ArrayAdapter<T>, auquel on donnera le layout de ligne par défaut simple, identifié par android.R.layout.simple_list_item_1.

ListView listView=getListView();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, maListe);
listView.setAdapter(adapter);

Ici (on est dans la méthode onCreate de l’activité) :

  • la méthode getListView() récupère une référence sur le container ListView qu’on aura pris soin de placer dans le fichier de layout de l’activité.
  • dans la seconde ligne on crée l’adapteur avec la liste et la référence au fichier de layout de la ligne. On utilise un layout de ligne par défaut.

TP

Créer une activité avec une liste en dur, de type ArrayList<String>, contenant quelques lignes. Afficher cette liste dans l’activité.

TP (solution)

Voici d’abord le fichier de layout.

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

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

et le code java l’activité.

public class MainActivity extends ListActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<String> maListe=new ArrayList<String>();
        maListe.add("AAAAA");
        maListe.add("BBBBB");
        maListe.add("CCCCC");
        maListe.add("DDDDD");
        maListe.add("EEEEE");

        ListView listView=this.getListView();
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, maListe);
        listView.setAdapter(adapter);


    }
}

Liste composite, avec son adapteur

Cette fois-ci on souhaite afficher une liste dans laquelle on pourra afficher plusieurs informations, avec une mise en page particulière.

On va alors créer un fichier de layout correspondant à notre besoin.
Layout de ligne

Sur cette copie d’écran on voit une ligne qui sera composée d’un champs de texte affiché en gros avec en dessous 2 champs de textes plus petit, l’un à gauche de l’écran, l’autre, en Italique, à droite.

Ensuite un va créer un adapteur dans lequel on définira ce qui doit être affiché dans chacun des des champs, via la méthode getView(int position, @Nullable View convertView, @NonNull ViewGroup parent). position correspond à l’élément de la liste. la fonction get View va créer une ligne de la liste en plaçant les valeurs de cet élément (position) de la liste dans le layout de liste. le système appellera donc getView pour chacune des lignes.

TP

Reprendre la première partie, remplacer la liste de chaînes de caractères par une liste plus compliquée, ou chaque élément contient plusieurs valeurs (au moins 3). On pourra par exemple créer une classe pour stocker ces objets. Créer ensuite l’adapteur permettant de d’afficher la liste sous la forme indiquée sur la copie d’écran montrée plus haut.

Voir une copie d’écran du résultat attendu

TP (solution)

On va créer une classe objet comprenant 3 chaînes de caractères.

public class MyObject {
    private String str1, str2, str3;
    private String Str2;
    private String Str3;

    public MyObject(String str1, String str2, String str3) {
        this.str1 = str1;
        this.str2 = str2;
        this.str3 = str3;
    }

On la complètera avec une méthode toStringet des methodes de type getters pour récupérer chacune des 3 chaînes de caractères :

public class MyObject {
    public String getStr1() {
        return this.str1;
    }

Voici le code du layout de ligne my_list_row.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="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="30sp"
        android:textStyle="bold" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="TextView" />

        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="TextView"
            android:textAlignment="textEnd"
            android:textStyle="italic" />
    </LinearLayout>
</LinearLayout>

On crée ensuite l’adapteur :

public class MyAdapter extends ArrayAdapter<MyObject> {

    public MyAdapter(@NonNull Context context, @NonNull List<MyObject> objects) {
        super(context, R.layout.my_list_row, objects);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        LayoutInflater inflater=(LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View myRowView = inflater.inflate(R.layout.my_list_row, parent, false);

        TextView tv1=myRowView.findViewById(R.id.textView1);
        TextView tv2=myRowView.findViewById(R.id.textView2);
        TextView tv3=myRowView.findViewById(R.id.textView3);

        tv1.setText(this.getItem(position).getStr1());
        tv2.setText(this.getItem(position).getStr2());
        tv3.setText(this.getItem(position).getStr3());

        return myRowView;
    }
}

Ici l’inflaterva créer la vue correspondant à une ligne particulière, on va ensuite récupérer les références aux différents textView et leur assigner les valeurs en provenance de la classe myObject.

Enfin il reste à appeler cet adapteur dans le onCreate de l’activité principale (ListActivity) :

ListView listView=this.getListView();
MyAdapter adapter=new MyAdapter(this, maListe);
listView.setAdapter(adapter);

Données récupérées dans la base de données

Dans ce cas, les données sont récupérées dans la base grâce à une requête SQL (voir les éléments de cours Enregistrer des données)

On commence par créer un fichier de layout pour la ligne.

Comme on l’a vu dans ce cours, la méthode query renvoie un objet de type Cursor. Il reste à faire un adapteur pour adapter un cursor à notre layout de ligne.

TP

Reprendre le TP2 (enregistrement de données), ajouter une activité pour afficher la liste des données enregistrées (voir le cours sur les Intents. Créer maintenant un adapteur pour afficher les résultats de notre requête dans la liste.