Partager via


Personnalisation de l’apparence d’un ListView avec Xamarin.Android

L’apparence d’un ListView est dictée par la disposition des lignes affichées. Pour modifier l’apparence d’un ListView, utilisez une autre disposition de ligne.

Vues de lignes intégrées

Douze vues intégrées peuvent être référencées à l’aide d’Android.Resource.Layout :

  • TestListItem : ligne de texte unique avec une mise en forme minimale.

  • SimpleListItem1 : ligne de texte unique.

  • SimpleListItem2 : deux lignes de texte.

  • SimpleSelectableListItem : ligne de texte unique qui prend en charge la sélection d’un ou plusieurs éléments (ajoutée au niveau de l’API 11).

  • SimpleListItemActivated1 : similaire à SimpleListItem1, mais la couleur d’arrière-plan indique quand une ligne est sélectionnée (ajoutée au niveau de l’API 11).

  • SimpleListItemActivated2 : similaire à SimpleListItem2, mais la couleur d’arrière-plan indique quand une ligne est sélectionnée (ajoutée au niveau de l’API 11).

  • SimpleListItemChecked : affiche les coches pour indiquer la sélection.

  • SimpleListItemMultipleChoice : affiche les cases à cocher pour indiquer la sélection à choix multiple.

  • SimpleListItemSingleChoice : affiche les cases d’option pour indiquer une sélection mutuellement exclusive.

  • TwoLineListItem : deux lignes de texte.

  • ActivityListItem : ligne de texte unique avec une image.

  • SimpleExpandableListItem : regroupe les lignes par catégories, et chaque groupe peut être développé ou réduit.

Chaque vue de ligne intégrée a un style intégré qui lui est associé. Ces captures d’écran montrent comment chaque affichage s’affiche :

Captures d’écran de TestListItem, SimpleSelectableListItem, SimpleListitem1 et SimpleListItem2

Captures d’écran de SimpleListItemActivated1, SimpleListItemActivated2, SimpleListItemChecked et SimpleListItemMultipleChecked

Captures d’écran de SimpleListItemSingleChoice, TwoLineListItem, ActivityListItem et SimpleExpandableListItem

L’exemple de fichier BuiltInViews/HomeScreenAdapter.cs (dans la solution BuiltInViews ) contient le code pour produire les écrans des éléments de liste non extensibles. La vue est définie dans la GetView méthode comme suit :

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);

Les propriétés de la vue peuvent ensuite être définies en référençant les identificateurs Text1de contrôle standard, Text2 et Icon sous Android.Resource.Id (ne définissez pas les propriétés que la vue ne contient pas ou une exception sera levée) :

view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = item.Heading;
view.FindViewById<TextView>(Android.Resource.Id.Text2).Text = item.SubHeading;
view.FindViewById<ImageView>(Android.Resource.Id.Icon).SetImageResource(item.ImageResourceId); // only use with ActivityListItem

L’exemple de fichier BuiltInExpandableViews/ExpandableScreenAdapter.cs (dans la solution BuiltInViews ) contient le code pour produire l’écran SimpleExpandableListItem. L’affichage de groupe est défini dans la GetGroupView méthode comme suit :

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem1, null);

La vue enfant est définie dans la GetChildView méthode comme suit :

view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleExpandableListItem2, null);

Les propriétés de l’affichage de groupe et de l’affichage enfant peuvent ensuite être définies en référençant les identificateurs standard Text1 et Text2 de contrôle comme indiqué ci-dessus. La capture d’écran SimpleExpandableListItem (illustrée ci-dessus) fournit un exemple d’affichage de groupe à une ligne (SimpleExpandableListItem1) et d’une vue enfant à deux lignes (SimpleExpandableListItem2). Sinon, l’affichage de groupe peut être configuré pour deux lignes (SimpleExpandableListItem2) et la vue enfant peut être configurée pour une seule ligne (SimpleExpandableListItem1), ou l’affichage groupe et l’affichage enfant peuvent avoir le même nombre de lignes.

Accessories

Les lignes peuvent avoir des accessoires ajoutés à droite de la vue pour indiquer l’état de sélection :

  • SimpleListItemChecked : crée une liste de sélection unique avec une vérification en tant qu’indicateur.

  • SimpleListItemSingleChoice : crée des listes de type case d’option où un seul choix est possible.

  • SimpleListItemMultipleChoice : crée des listes de type case à cocher où plusieurs choix sont possibles.

Les accessoires mentionnés ci-dessus sont illustrés dans les écrans suivants, dans leur ordre respectif :

Captures d’écran de SimpleListItemChecked, SimpleListItemSingleChoice et SimpleListItemMultipleChoice avec accessoires

Pour afficher l’un de ces accessoires, passez l’ID de ressource de disposition requis à l’adaptateur, puis définissez manuellement l’état de sélection pour les lignes requises. Cette ligne de code montre comment créer et affecter une Adapter application à l’aide de l’une de ces dispositions :

ListAdapter = new ArrayAdapter<String>(this, Android.Resource.Layout.SimpleListItemChecked, items);

Elle-même ListView prend en charge différents modes de sélection, quel que soit l’accessoire affiché. Pour éviter toute confusion, utilisez Single le mode sélection avec SingleChoice des accessoires et le ou Multiple le Checked mode avec le MultipleChoice style. Le mode de sélection est contrôlé par la ChoiceMode propriété du ListView.

Gestion du niveau d’API

Les versions antérieures de Xamarin.Android implémentent des énumérations en tant que propriétés entières. La dernière version a introduit des types d’énumération .NET appropriés qui facilitent beaucoup la découverte des options potentielles.

Selon le niveau d’API que vous ciblez, ChoiceMode il s’agit d’un entier ou d’une énumération. L’exemple de fichier AccessoryViews/HomeScreen.cs a un commentaire bloqué si vous souhaitez cibler l’API Gingerbread :

// For targeting Gingerbread the ChoiceMode is an int, otherwise it is an
// enumeration.

lv.ChoiceMode = Android.Widget.ChoiceMode.Single; // 1
//lv.ChoiceMode = Android.Widget.ChoiceMode.Multiple; // 2
//lv.ChoiceMode = Android.Widget.ChoiceMode.None; // 0

// Use this block if targeting Gingerbread or lower
/*
lv.ChoiceMode = 1; // Single
//lv.ChoiceMode = 0; // none
//lv.ChoiceMode = 2; // Multiple
//lv.ChoiceMode = 3; // MultipleModal
*/

Sélection d’éléments par programmation

La définition manuelle des éléments « sélectionnés » est effectuée avec la SetItemChecked méthode (elle peut être appelée plusieurs fois pour plusieurs sélections) :

// Set the initially checked row ("Fruits")
lv.SetItemChecked(1, true);

Le code doit également détecter les sélections uniques différemment de plusieurs sélections. Pour déterminer quelle ligne a été sélectionnée en Single mode, utilisez la CheckedItemPosition propriété integer :

FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPosition

Pour déterminer quelles lignes ont été sélectionnées en Multiple mode, vous devez effectuer une boucle dans le CheckedItemPositions SparseBooleanArray. Un tableau partiellement alloué est semblable à un dictionnaire qui contient uniquement les entrées où la valeur a été modifiée. Vous devez donc parcourir l’ensemble du tableau à la recherche true de valeurs pour savoir ce qui a été sélectionné dans la liste, comme illustré dans l’extrait de code suivant :

var sparseArray = FindViewById<ListView>(Android.Resource.Id.List).CheckedItemPositions;
for (var i = 0; i < sparseArray.Size(); i++ )
{
   Console.Write(sparseArray.KeyAt(i) + "=" + sparseArray.ValueAt(i) + ",");
}
Console.WriteLine();

Création de dispositions de lignes personnalisées

Les quatre vues de lignes intégrées sont très simples. Pour afficher des dispositions plus complexes (telles qu’une liste d’e-mails, de tweets ou d’informations de contact), une vue personnalisée est requise. Les vues personnalisées sont généralement déclarées en tant que fichiers AXML dans le répertoire Ressources/Disposition , puis chargées à l’aide de leur ID de ressource par un adaptateur personnalisé. La vue peut contenir n’importe quel nombre de classes d’affichage (telles que TextViews, ImageViews et autres contrôles) avec des couleurs, polices et disposition personnalisées.

Cet exemple diffère des exemples précédents de plusieurs façons :

  • Hérite de Activity , et non ListActivity . Vous pouvez personnaliser des lignes pour n’importe quel ListView contrôle, mais d’autres contrôles peuvent également être inclus dans une Activity disposition (par exemple, un titre, des boutons ou d’autres éléments d’interface utilisateur). Cet exemple montre comment ajouter un titre au-dessus de l’illustration ListView .

  • Nécessite un fichier de disposition AXML pour l’écran ; dans les exemples précédents, il ListActivity n’a pas besoin d’un fichier de disposition. Cet AXML contient une ListView déclaration de contrôle.

  • Nécessite un fichier de disposition AXML pour afficher chaque ligne. Ce fichier AXML contient les contrôles texte et image avec des paramètres de police et de couleur personnalisés.

  • Utilise un fichier XML de sélecteur personnalisé facultatif pour définir l’apparence de la ligne lorsqu’elle est sélectionnée.

  • L’implémentation Adapter retourne une disposition personnalisée à partir de la GetView substitution.

  • ItemClick doit être déclaré différemment (un gestionnaire d’événements est attaché au ListView.ItemClick lieu d’un remplacement OnListItemClick dans ListActivity).

Ces modifications sont détaillées ci-dessous, en commençant par créer l’affichage de l’activité et l’affichage de ligne personnalisé, puis en couvrant les modifications apportées à l’adaptateur et à l’activité pour les afficher.

Ajout d’un ListView à une disposition d’activité

Comme HomeScreen il n’hérite plus d’elle ListActivity n’a pas d’affichage par défaut, un fichier AXML de disposition doit donc être créé pour l’affichage de HomeScreen. Pour cet exemple, la vue aura un titre (à l’aide d’un TextView) et un ListView pour afficher les données. La disposition est définie dans le fichier Resources/Layout/HomeScreen.axml qui est illustré ici :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
    <TextView android:id="@+id/Heading"
        android:text="Vegetable Groups"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        android:textSize="30dp"
        android:textColor="#FF267F00"
        android:textStyle="bold"
        android:padding="5dp"
    />
    <ListView android:id="@+id/List"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#FFDAFF7F"
    />
</LinearLayout>

L’avantage de l’utilisation d’une Activity disposition personnalisée (au lieu d’un ListActivity) réside dans la possibilité d’ajouter des contrôles supplémentaires à l’écran, tels que le titre TextView de cet exemple.

Création d’une disposition de ligne personnalisée

Un autre fichier de disposition AXML est requis pour contenir la disposition personnalisée pour chaque ligne qui apparaîtra dans l’affichage liste. Dans cet exemple, la ligne aura un arrière-plan vert, du texte brun et une image alignée à droite. Le balisage XML Android pour déclarer cette disposition est décrit dans Resources/Layout/CustomView.axml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:background="#FFDAFF7F"
   android:padding="8dp">
    <LinearLayout android:id="@+id/Text"
       android:orientation="vertical"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:paddingLeft="10dip">
        <TextView
         android:id="@+id/Text1"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textColor="#FF7F3300"
         android:textSize="20dip"
         android:textStyle="italic"
         />
        <TextView
         android:id="@+id/Text2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textSize="14dip"
         android:textColor="#FF267F00"
         android:paddingLeft="100dip"
         />
    </LinearLayout>
    <ImageView
        android:id="@+id/Image"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:padding="5dp"
        android:src="@drawable/icon"
        android:layout_alignParentRight="true" />
</RelativeLayout >

Bien qu’une disposition de ligne personnalisée puisse contenir de nombreux contrôles différents, les performances de défilement peuvent être affectées par des conceptions complexes et l’utilisation d’images (en particulier s’ils doivent être chargés sur le réseau). Pour plus d’informations sur la résolution des problèmes de performances de défilement, consultez l’article de Google.

Référencement d’une vue de ligne personnalisée

L’implémentation de l’exemple d’adaptateur personnalisé est dans HomeScreenAdapter.cs. La méthode clé est GetView l’emplacement où elle charge l’AXML personnalisé à l’aide de l’ID Resource.Layout.CustomViewde ressource, puis définit les propriétés sur chacun des contrôles de l’affichage avant de le renvoyer. La classe d’adaptateur complète s’affiche :

public class HomeScreenAdapter : BaseAdapter<TableItem> {
   List<TableItem> items;
   Activity context;
   public HomeScreenAdapter(Activity context, List<TableItem> items)
       : base()
   {
       this.context = context;
       this.items = items;
   }
   public override long GetItemId(int position)
   {
       return position;
   }
   public override TableItem this[int position]
   {
       get { return items[position]; }
   }
   public override int Count
   {
       get { return items.Count; }
   }
   public override View GetView(int position, View convertView, ViewGroup parent)
   {
       var item = items[position];
       View view = convertView;
       if (view == null) // no view to re-use, create new
           view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
       view.FindViewById<TextView>(Resource.Id.Text1).Text = item.Heading;
       view.FindViewById<TextView>(Resource.Id.Text2).Text = item.SubHeading;
       view.FindViewById<ImageView>(Resource.Id.Image).SetImageResource(item.ImageResourceId);
       return view;
   }
}

Référencement du ListView personnalisé dans l’activité

Étant donné que la HomeScreen classe hérite Activitymaintenant de , un ListView champ est déclaré dans la classe pour contenir une référence au contrôle déclaré dans l’AXML :

ListView listView;

La classe doit ensuite charger la disposition personnalisée de l’activité AXML à l’aide de la SetContentView méthode. Il peut ensuite trouver le ListView contrôle dans la disposition, puis crée et affecte l’adaptateur et affecte le gestionnaire de clics. Le code de la méthode OnCreate est illustré ici :

SetContentView(Resource.Layout.HomeScreen); // loads the HomeScreen.axml as this activity's view
listView = FindViewById<ListView>(Resource.Id.List); // get reference to the ListView in the layout

// populate the listview with data
listView.Adapter = new HomeScreenAdapter(this, tableItems);
listView.ItemClick += OnListItemClick;  // to be defined

Enfin, le ItemClick gestionnaire doit être défini ; dans ce cas, il affiche simplement un Toast message :

void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
   var listView = sender as ListView;
   var t = tableItems[e.Position];
   Android.Widget.Toast.MakeText(this, t.Heading, Android.Widget.ToastLength.Short).Show();
}

L’écran obtenu ressemble à ceci :

Capture d’écran du CustomRowView résultant

Personnalisation de la couleur du sélecteur de lignes

Lorsqu’une ligne est touchée, elle doit être mise en surbrillance pour les commentaires des utilisateurs. Lorsqu’une vue personnalisée spécifie comme couleur d’arrière-plan comme CustomView.axml , elle remplace également la surbrillance de la sélection. Cette ligne de code dans CustomView.axml définit l’arrière-plan sur vert clair, mais cela signifie également qu’il n’existe aucun indicateur visuel lorsque la ligne est touchée :

android:background="#FFDAFF7F"

Pour réactiver le comportement de mise en surbrillance, et également pour personnaliser la couleur utilisée, définissez plutôt l’attribut d’arrière-plan sur un sélecteur personnalisé. Le sélecteur déclare à la fois la couleur d’arrière-plan par défaut ainsi que la couleur de surbrillance. Le fichier Resources/Drawable/CustomSelector.xml contient la déclaration suivante :

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
  android:state_selected="false"
  android:drawable="@color/cellback" />
<item android:state_pressed="true" >
  <shape>
     <gradient
      android:startColor="#E77A26"
        android:endColor="#E77A26"
        android:angle="270" />
  </shape>
</item>
<item android:state_selected="true"
  android:state_pressed="false"
  android:drawable="@color/cellback" />
</selector>

Pour référencer le sélecteur personnalisé, remplacez l’attribut d’arrière-plan dans CustomView.axml par :

android:background="@drawable/CustomSelector"

Une ligne sélectionnée et le message correspondant Toast ressemblent maintenant à ceci :

Ligne sélectionnée en orange, avec message Toast affichant le nom de la ligne sélectionnée

Prévention du scintillement sur des dispositions personnalisées

Android tente d’améliorer les performances du ListView défilement en mettant en cache les informations de disposition. Si vous avez de longues listes de données à défilement, vous devez également définir la android:cacheColorHint propriété sur la déclaration dans la ListView définition AXML de l’activité (avec la même valeur de couleur que l’arrière-plan de votre disposition de ligne personnalisée). L’échec de l’ajout de cet indicateur peut entraîner un « scintillement » lorsque l’utilisateur fait défiler une liste avec des couleurs d’arrière-plan de ligne personnalisées.