Nous allons voir une View particulière d’Android la ListView. Elle est utilisée pour montrer un ensemble de résultats à un utilisateur comme par exemple le résultat d’une recherche, la liste est scrollable. Afin de créer cette View, on utilise ce qu’on appelle un Adapter, ce dernier est associé à notre ListView. Voici le résultat de l’exemple de cet article, qui permet d’afficher l’image d’un film et son titre associé.
ArrayAdapter
Un ArrayAdapter (hérite de la classe BaseAdapter) permet de gérer le modèle qui va permettre de créer la ListView. Chaque ligne qui est affichée dans une ListView est constitué d’un layout, qui peut-être aussi complexe que l’on désire. Quand on veut simplement créer une liste composée de chaîne par exemple, on peut utiliser un des constructeurs par défaut :
private final String[] movies = new String[] { "Independence day", "The fifth element", "The last samurai" }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ListView list = (ListView) findViewById(R.id.list_links); list.setAdapter(new ArrayAdapter<String>(this, R.layout.list_result, movies)); }
En effet la classe ArrayAdapter peut gérer une liste de tableaux d’objets java (Integer, String…). Chaque objet sera alors mappé avec une cellule. La classe propose alors quelques méthodes intéressantes :
- La classe propose une méthode pour supprimer tous les éléments présents grâce à la méthode clear().
- On retrouve également deux méthodes pour ajouter des éléments, la fonction add() et la fonction addAll() qui permet d’ajouter une Collection.
- Il est également possible d’effectuer directement des actions sur la liste qui vous a servi à créer votre Adapter. Ensuite, vous n’aurez plus qu’à utiliser la méthode notifyDataSetChanged(), l’Adapter sera alors notifié des changements et la liste se mettra à jour automatiquement.
Exemple de construction d’une listview
Maintenant, si on veut réaliser notre liste à partir d’un objet comment faire ? On va tout simplement créer notre propre Adapter, pour se faire on va faire hériter notre classe de ArrayAdapter. Voyons donc tout cela à travers d’un exemple. On va chercher à créer une liste permettant d’afficher l’image d’un film ainsi que son titre (par la suite il vous sera très simple d’ajouter par exemple le réalisateur ou encore le synopsis).
Commençons par réaliser notre objet Movie, représenté par le titre du film et le chemin vers les images situées dans le dossier drawable d’Android, si vous ne connaissez pas le principe des Drawables je vous laisse lire la documentation vil mécréant ! Ensuite, on créé simplement un constructeur, les accesseurs et mutateurs des attributs.
package com.lv.listview; public class Movie { private String _title; private Integer _cover; public Movie(String title, Integer cover) { _title = title; _cover = cover; } public String getTitle() { return _title; } public Integer getCover() { return _cover; } }
Voyons maintenant, le layout principal qui contiendra notre ListView.
<ListView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/list_movies" android:layout_margin="0dp" android:padding="0dp" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.lv.listview.MainActivity" />
Création de notre activité
Passons maintenant à la construction de notre activité. Tout d’abord, on créer une liste chaînée d’objets Movie et on y ajoute trois films. Ensuite, on récupère la ListView grâce à l’id list_movies. On crée notre Adapter et on le passe à la ListView grâce à la méthode setAdapter(). Enfin on créé et set un event listener, qu’on expliquera un peu plus tard.
package com.lv.listview; import java.util.LinkedList; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Toast; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LinkedList<Movie> movies = new LinkedList<Movie>(); movies.add(new Movie("Independence day", R.drawable.independence_day)); movies.add(new Movie("The fifth element", R.drawable.the_fifth_element)); movies.add(new Movie("The last samurai", R.drawable.the_last_samurai)); MovieAdaptater adapter = new MovieAdaptater(getApplicationContext(), R.layout.activity_item, movies); ListView list_movies = (ListView) findViewById(R.id.list_movies); list_movies.setAdapter(adapter); list_movies.setOnItemClickListener(listview_listerner); } OnItemClickListener listview_listerner = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, int position, long id) { View titleView = view.findViewById(R.id.title); String title = (String) titleView.getTag(); Toast.makeText(getApplicationContext(), title, Toast.LENGTH_SHORT).show(); } }; }
Comme on l’a vu, on peut créer un layout pour chaque item de la ListView. Donc rien de compliquer un LinearLayout avec une orientation horizontale. Une ImageView qui prendra 35% en largeur et un TextView qui prendra 65% de la largeur.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="5dp"> <ImageView android:id="@+id/cover" android:layout_width="0dp" android:layout_height="160dp" android:layout_marginRight="6dip" android:layout_weight="0.35" android:contentDescription="" /> <TextView android:id="@+id/title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.65" android:text="Title" /> </LinearLayout>
Création de notre Adapter
Enfin, maintenant, voyons la création de notre Adapter, on fait donc hériter notre classe de ArrayAdapter. Il y a une méthode que l’on doit définir, c’est la méthode getView(). Elle est utilisée afin de créer la liste ou encore la mettre à jour.
Voyons les arguments, la position représente tout simplement l’index de l’item ajouté. La convertView, c’est tout simplement la vue qui est en train d’être créé, si cette dernière existe déjà (en cas de mise à jour de la liste par exemple), il suffit de la récupérer. Après, on récupère tout simplement l’ImageView et le TextView précédemment créé et on les modifie afin d’afficher les valeurs d’un objet Movie.
Enfin, on utilise la méthode setTag() du TextView afin de pouvoir le récupérer par la suite dans notre event.
package com.lv.listview; import java.util.LinkedList; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; public class MovieAdaptater extends ArrayAdapter<Movie> { private final Context _context; private LinkedList<Movie> _movies; public MovieAdaptater(Context context, int resource, LinkedList<Movie> movies) { super(context, resource, movies); _context = context; _movies = movies; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null) { LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.activity_item, parent, false); } else { convertView = (LinearLayout) convertView; } ImageView imageView = (ImageView) convertView.findViewById(R.id.cover); imageView.setBackgroundResource(_movies.get(position).getCover()); TextView viewTitle = (TextView) convertView.findViewById(R.id.title); viewTitle.setText(_movies.get(position).getTitle()); viewTitle.setTag(_movies.get(position).getTitle()); return convertView; } }
Enfin, voyons maintenant notre event listener créé dans la première partie. Notre event est un OnItemClickListener,event utilisé lors d’un clic sur une cellule d’une ListView. Ici on ne réalise pas grand-chose, on récupère la vue sur laquelle on a cliqué et on récupère le titre du film grâce à la méthode getTag().