Imprimer
Catégorie : Interfaces Utilisateur
Affichages : 7

La Boîte à Outils Android Widget

 Android fournit une boîte à outils de vues standard pour vous aider à créer vos interfaces utilisateur. En utilisant ces contrôles (et en les modifiant ou en les développant au besoin), vous pouvez simplifier votre développement et assurer la cohérence entre les applications et avec l'interface utilisateur du système Android. La liste suivante présente certaines des commandes les plus courantes:

 Travailler avec les listes et les grilles

Lorsque vous devez afficher un grand ensemble de données dans votre interface utilisateur, il peut être tentant d’ajouter des centaines de

Vues sur votre interface utilisateur. C'est presque toujours la mauvaise approche. RecyclerView (disponible dans la bibliothèque de support Android) propose plutôt un groupe de vues à défilement spécialement conçu pour afficher et faire défiler efficacement un grand nombre d'éléments.

La vue Recycler peut être utilisée dans les orientations verticale et horizontale, configurée à l'aide de l'attribut android: orientation:

< android.support.v7.widget.RecyclerView

  xmlns:android:"http://schemas.android.com/apk/res/android"   xmlns:app="http://schemas.android.com/apk/res-auto"

  android:id="@+id/recycler_view"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:orientation="vertical"

  [... Layout Manager Attributes ...]

/>

Dans une orientation verticale, les éléments sont disposés de haut en bas et la vue Recycleur défile verticalement, tandis qu'une orientation horizontale les disposera de gauche à droite et la vue Recycleur défilera horizontalement.

 Gestionnaires de vue et de mise en page du recycleur

 RecyclerView lui-même ne contrôle pas la façon dont chaque élément est affiché; cette responsabilité appartient à RecyclerView.LayoutManager associé. Cette séparation des tâches vous permet de remplacer les classes du gestionnaire de disposition sans affecter d’autres parties de votre application.

Un certain nombre de gestionnaires de disposition sont disponibles, comme illustré à la figure 5-4 et décrits ici:

 Le gestionnaire de disposition fonctionne de la même manière qu'une disposition standard: elle est responsable de la disposition des vues représentant chaque élément de votre jeu de données.

La vue Recycler tire son nom de la façon dont elle prend en charge le défilement. Plutôt que de créer une vue pour chaque élément dès le départ, ou de les créer continuellement quand ils sont défilés, la vue Recycleur est en mesure de «recycler» les vues existantes qui ne sont plus visibles - en modifiant leur contenu et leur position pour représenter les éléments récemment visibles.

Pour prendre en charge ce problème, le gestionnaire de disposition est également chargé de déterminer le moment où une vue peut être recyclée en toute sécurité. Dans la plupart des cas, cela permet à la vue Recycleur de prendre en charge une liste presque infinie (226) d'éléments, tout en créant juste assez de vues pour remplir un seul écran.

Le gestionnaire de disposition pour une vue du recycleur peut être défini en XML ou par programme.

Par exemple, l'extrait de code suivant présente une vue de recycleur alignée verticalement avec un gestionnaire de disposition de grille comportant deux colonnes:

 < android.support.v7.widget.RecyclerView

  xmlns:android:"http://schemas.android.com/apk/res/android"   xmlns:app="http://schemas.android.com/apk/res-auto"   android:id="@+id/recycler_view"   android:layout_width="match_parent"   android:layout_height="match_parent"   android:orientation="vertical"   app:layoutManager="GridLayoutManager"

  app:spanCount="2" />

Pour attribuer le même gestionnaire de disposition dans le code, vous utiliseriez l'extrait suivant pour une vue Recycler existante:

 RecyclerView recyclerView = findViewById(R.id.recycler_view);

GridLayoutManager gridLayoutManager = new GridLayoutManager(2); recyclerView.setLayoutManager(gridLayoutManager);

 Présentation des adaptateurs

 Les gestionnaires de disposition ne sont particulièrement utiles que lorsque vous avez les données à afficher; ces données sont fournies par RecyclerView.Adapter. L'adaptateur a deux rôles importants:

 Un détenteur de vue stocke la vue à afficher et permet également à l'adaptateur de stocker des métadonnées et des références de vue supplémentaires pour simplifier la liaison de données, comme indiqué ultérieurement. Cela inclut généralement la recherche de références à des vues enfant dans la présentation d'un élément (afin que le travail ne soit effectué qu'une seule fois).

La méthode onCreateViewHolder de l’adaptateur est appelée pour obtenir une nouvelle instance RecyclerView.ViewHolder chaque fois que le gestionnaire d’affichage ne dispose pas d’une vue inutilisée à réutiliser - en règle générale, il ne reste que suffisamment de vues pour remplir l’écran.

Le Listing 5-4 montre une implémentation simple d'adaptateur utilisant une seule vue de texte pour afficher des données stockées dans un tableau de chaînes.

LISTING 5-4 : Créer un adaptateur de recycleur

public class SimpleAdapter   extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {

  // Underlying data to be displayed. 

  private String[] mData; 

  // Set the initial data in the constructor   public SimpleAdapter(String[] data) {

    mData = data;

  }

  // Tell the Layout Manager how many items exist in the data

  @Override

  public int getItemCount() {

    return mData == null ? 0 : mData.length;   }

  public static class ViewHolder extends RecyclerView.ViewHolder {     public TextView textView;

    public ViewHolder(View v) {

      super(v);

      // Only do findViewById once       textView = v.findViewById(R.id.text);

    }

  }

  @Override

  public SimpleAdapter.ViewHolder onCreateViewHolder(

      ViewGroup parent, int viewType) {

    // Create the new View

    View v = LayoutInflater.from(parent.getContext())

               .inflate(R.layout.simple_text, parent, false);

    return new ViewHolder(v);   }

Notez que le détenteur de la vue n’attribue pas de valeurs des données sous-jacentes aux vues qu’il contient. Son rôle est de rendre les éléments de la présentation de la vue disponibles pour que l’adaptateur puisse y lier des données.

À chaque fois qu'un élément doit être affiché, le Gestionnaire de mise en page appelle la méthode onBindViewHolder de l'adaptateur, en vous fournissant un ViewHolder créé précédemment et la position demandée dans le jeu de données. Cette phase de liaison est très fréquente lors du défilement d'une liste (une fois pour chaque élément défilant dans la vue), elle doit donc être aussi légère que possible.

@Override

public void onBindViewHolder(ViewHolder holder, int position) {

  holder.textView.setText(mData[position]); }

Remarque Lors de la liaison d’un nouvel élément de données, il est important de réinitialiser tout élément View précédemment défini. Etant donné que le titulaire de la vue (et ses éléments de vue) sont constamment réutilisés, ils conservent tous les états définis lors d'appels précédents onBindViewHolder.

 Pour affecter votre adaptateur à une vue du recycleur, utilisez la méthode setAdapter:

 RecyclerView recyclerView = findViewById(R.id.recycler_view);

SimpleAdapter adapter =   new SimpleAdapter(new String[] {"Sample", "Sample 2"}); recyclerView.setAdapter(adapter);

 Les jeux de données statiques tels que cet exemple sont amusants, mais en réalité, nous sommes rarement aussi chanceux. Dans la plupart des cas, les données sous-jacentes changent lorsque de nouvelles données sont chargées à partir du serveur, si l'utilisateur ajoute ou supprime un élément, ou même si l'ordre de tri est modifié.

Lorsque vous mettez à jour un adaptateur avec des données nouvelles ou modifiées, vous devez appeler l’une des méthodes de notification de l’adaptateur pour informer le gestionnaire de disposition que quelque chose a changé. RecyclerView animera ensuite une transition entre les états précédent et mis à jour (fondus croisés des éléments modifiés, réduction et suppression des éléments supprimés et animation de nouveaux éléments).

Vous pouvez personnaliser les animations utilisées pour chaque changement d'état en affectant un. RecyclerView .ItemAnimator à l'aide de la méthode setItemAnimator.

Il existe différentes méthodes pour notifier le changement, l'insertion, le déplacement ou la suppression d'un seul élément et pour une gamme d'éléments. Vous pouvez utiliser la classe DiffUtil pour comprendre quelles modifications doivent être appliquées pour passer d'un jeu de données à un autre, comme indiqué dans le Listing 5-5.

 LISTING 5-5: Calcul des transitions entre les jeux de données

 public class SimpleAdapter

  extends RecyclerView.Adapter<SimpleAdapter.ViewHolder> {

  [... Existing SimpleAdapter Implementation ...]

  public void setData(final String[] newData) {

    // Store a copy of the previous data     final String[] previousData = mData;

    // apply the new data     mData = newData;

    // Calculate the differences between the old and new data

    DiffUtil.calculateDiff(new DiffUtil.Callback() {

      @Override

      public int getOldListSize() {

        return previousData != null ? previousData.length : 0;       }

      @Override

      public int getNewListSize() {

        return newData != null ? previousData.length : 0;

      }           

      @Override

      public boolean areItemsTheSame(int oldItemPosition,                                      int newItemPosition) {

        // This method should compare the item's unique identifiers         // if available. Returning true means the two items should be

        // crossfaded. In this example, we don't have an identifier,

        // so we'll compare the string values.

        return TextUtils.equals(previousData[oldItemPosition],                                 newData[newItemPosition]);

      }

      @Override

      public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {  // This method should do a deep inspection of the items to determine    // if their visible contents are the same.

       // If they are the same, no animation is required.

       // In this example, if the items are the same,

       // the contents are the same

       return true;

     }

   }).dispatchUpdatesTo(this);

  }

}