Partager via


Exemple RecyclerView de base

Pour comprendre comment RecyclerView fonctionne dans une application classique, cette rubrique explore un exemple de code simple qui utilise RecyclerView pour afficher une grande collection de photos :

Deux captures d’écran d’une application RecyclerView qui utilise CardViews pour afficher des photos

RecyclerViewer utilise CardView pour implémenter chaque élément de photographie dans la RecyclerView disposition. En raison des avantages de RecyclerViewperformances de cet exemple d’application, cet exemple d’application peut faire défiler rapidement une grande collection de photos en douceur et sans retards notables.

Exemple de source de données

Dans cet exemple d’application, une source de données « album photo » (représentée par la PhotoAlbum classe) fournit RecyclerView du contenu d’élément. PhotoAlbum est une collection de photos avec des légendes ; lorsque vous l’instanciez, vous obtenez une collection prête à l’usage de 32 photos :

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

Chaque instance de photo dans PhotoAlbum expose des propriétés qui vous permettent de lire son ID de ressource d’image, PhotoIDet sa chaîne de légende. Caption La collection de photos est organisée de telle sorte que chaque photo soit accessible par un indexeur. Par exemple, les lignes de code suivantes accèdent à l’ID de ressource d’image et à la légende pour la dixième photo de la collection :

int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;

PhotoAlbum fournit également une RandomSwap méthode que vous pouvez appeler pour échanger la première photo de la collection avec une photo choisie de manière aléatoire ailleurs dans la collection :

mPhotoAlbum.RandomSwap ();

Étant donné que les détails de PhotoAlbum l’implémentation ne sont pas pertinents pour comprendre RecyclerView, le PhotoAlbum code source n’est pas présenté ici.

Disposition et initialisation

Le fichier de disposition, Main.axml, se compose d’un fichier unique RecyclerView au sein d’un LinearLayout:

<?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">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

Notez que vous devez utiliser le nom complet android.support.v7.widget.RecyclerView , car RecyclerView il est empaqueté dans une bibliothèque de support. La OnCreate méthode d’initialisation de MainActivity cette disposition, instancie l’adaptateur et prépare la source de données sous-jacente :

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Prepare the data source:
        mPhotoAlbum = new PhotoAlbum ();

        // Instantiate the adapter and pass in its data source:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);

        // Set our view from the "main" layout resource:
        SetContentView (Resource.Layout.Main);

        // Get our RecyclerView layout:
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug the adapter into the RecyclerView:
        mRecyclerView.SetAdapter (mAdapter);

Ce code effectue ce qui suit :

  1. Instancie la source de PhotoAlbum données.

  2. Transmet la source de données de l’album photo au constructeur de l’adaptateur ( PhotoAlbumAdapter qui est défini plus loin dans ce guide). Notez qu’il est considéré comme une bonne pratique de transmettre la source de données en tant que paramètre au constructeur de l’adaptateur.

  3. Obtient la RecyclerView disposition.

  4. Branche l’adaptateur dans l’instance RecyclerView en appelant la RecyclerView SetAdapter méthode comme indiqué ci-dessus.

Gestionnaire de disposition

Chaque élément de l’élément RecyclerView est constitué d’un CardView élément qui contient une image photo et une légende de photo (les détails sont abordés dans la section View Holder ci-dessous). Le prédéfini LinearLayoutManager est utilisé pour disposer chacun CardView dans une disposition de défilement verticale :

mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);

Ce code réside dans la méthode de l’activité OnCreate principale. Le constructeur du gestionnaire de disposition nécessite un contexte. Il MainActivity est donc passé à l’aide this comme indiqué ci-dessus.

Au lieu d’utiliser l’élément prédéfini LinearLayoutManager, vous pouvez brancher un gestionnaire de disposition personnalisé qui affiche deux CardView éléments côte à côte, implémentant un effet d’animation tournant de page pour parcourir la collection de photos. Plus loin dans ce guide, vous verrez un exemple de modification de la disposition en échangeant dans un autre gestionnaire de disposition.

Titulaire d’affichage

La classe titulaire d’affichage est appelée PhotoViewHolder. Chaque PhotoViewHolder instance contient des références à l’élément ImageView de ligne associé TextView , qui est présenté dans un CardView diagramme ici :

Diagramme de CardView contenant une imageView et TextView

PhotoViewHolder dérive des RecyclerView.ViewHolder propriétés et contient des propriétés pour stocker les références à la ImageView disposition ci-dessus et TextView affichées dans la disposition ci-dessus. PhotoViewHolder se compose de deux propriétés et d’un constructeur :

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

Dans cet exemple de code, le PhotoViewHolder constructeur est passé une référence à la vue d’élément parent (le CardView) qui PhotoViewHolder encapsule. Notez que vous transférez toujours la vue d’élément parent au constructeur de base. Le PhotoViewHolder constructeur appelle FindViewById la vue d’élément parent pour localiser chacune de ses références d’affichage enfant etTextViewImageView, en stockant les résultats dans les propriétés et Caption les Image résultats, respectivement. L’adaptateur récupère ultérieurement les références d’affichage de ces propriétés lorsqu’elle met à jour les CardViewvues enfants avec de nouvelles données.

Pour plus d’informations sur RecyclerView.ViewHolder, consultez la référence de la classe RecyclerView.ViewHolder.

Adaptateur

L’adaptateur charge chaque RecyclerView ligne avec des données pour une photographie particulière. Pour une photographie donnée à la position P de ligne, par exemple, l’adaptateur localise les données associées à la position P dans la source de données et copie ces données dans l’élément de ligne à la position P dans la RecyclerView collection. L’adaptateur utilise le titulaire d’affichage pour rechercher les références pour la ImageView position et TextView à cette position afin qu’il n’ait pas à appeler FindViewById à plusieurs reprises ces vues lorsque l’utilisateur fait défiler la collection de photographies et réutilise les vues.

Dans RecyclerViewer, une classe d’adaptateur est dérivée de RecyclerView.Adapter la création PhotoAlbumAdapter:

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;

    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }
    ...
}

Le mPhotoAlbum membre contient la source de données (l’album photo) transmise au constructeur ; le constructeur copie l’album photo dans cette variable membre. Les méthodes requises RecyclerView.Adapter suivantes sont implémentées :

  • OnCreateViewHolder : instancie le fichier de disposition d’élément et le titulaire d’affichage.

  • OnBindViewHolder : charge les données à la position spécifiée dans les vues dont les références sont stockées dans le titulaire de vue donné.

  • ItemCount : retourne le nombre d’éléments dans la source de données.

Le gestionnaire de disposition appelle ces méthodes alors qu’il positionne les éléments dans le RecyclerView. L’implémentation de ces méthodes est examinée dans les sections suivantes.

OnCreateViewHolder

Le gestionnaire de disposition appelle OnCreateViewHolder quand un RecyclerView nouveau titulaire d’affichage doit représenter un élément. OnCreateViewHolder gonfle l’affichage d’élément à partir du fichier de disposition de la vue et encapsule l’affichage dans une nouvelle PhotoViewHolder instance. Le PhotoViewHolder constructeur localise et stocke les références aux vues enfants dans la disposition, comme décrit précédemment dans View Holder.

Chaque élément de ligne est représenté par un CardView élément qui contient un ImageView (pour la photo) et un TextView (pour la légende). Cette disposition réside dans le fichier PhotoCardView.axml :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardElevation="4dp"
        card_view:cardUseCompatPadding="true"
        card_view:cardCornerRadius="5dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="8dp">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/imageView"
                android:scaleType="centerCrop" />
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="#333333"
                android:text="Caption"
                android:id="@+id/textView"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="4dp" />
        </LinearLayout>
    </android.support.v7.widget.CardView>
</FrameLayout>

Cette disposition représente un élément de ligne unique dans le RecyclerView. La OnBindViewHolder méthode (décrite ci-dessous) copie les données de la source de données dans la ImageView disposition et TextView dans celle-ci. OnCreateViewHoldergonfle cette disposition pour un emplacement photo donné dans l’instance RecyclerView et instancie une nouvelle PhotoViewHolder instance (qui localise et met en cache les références aux vues enfants et TextView aux ImageView vues enfants dans la disposition associéeCardView) :

public override RecyclerView.ViewHolder
    OnCreateViewHolder (ViewGroup parent, int viewType)
{
    // Inflate the CardView for the photo:
    View itemView = LayoutInflater.From (parent.Context).
                Inflate (Resource.Layout.PhotoCardView, parent, false);

    // Create a ViewHolder to hold view references inside the CardView:
    PhotoViewHolder vh = new PhotoViewHolder (itemView);
    return vh;
}

L’instance de titulaire d’affichage résultante est vhretournée à l’appelant (gestionnaire de disposition).

OnBindViewHolder

Lorsque le gestionnaire de disposition est prêt à afficher une vue particulière dans la zone d’écran visible de l’adaptateur RecyclerView, il appelle la méthode de OnBindViewHolder l’adaptateur pour remplir l’élément à la position de ligne spécifiée avec du contenu de la source de données. OnBindViewHolder obtient les informations de photo pour la position de ligne spécifiée (ressource d’image de la photo et chaîne de la légende de la photo) et copie ces données dans les vues associées. Les vues se trouvent via des références stockées dans l’objet titulaire de la vue (qui est transmis via le holder paramètre) :

public override void
    OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
    PhotoViewHolder vh = holder as PhotoViewHolder;

    // Load the photo image resource from the photo album:
    vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);

    // Load the photo caption from the photo album:
    vh.Caption.Text = mPhotoAlbum[position].Caption;
}

L’objet titulaire d’affichage passé doit d’abord être converti en type de titulaire d’affichage dérivé (dans ce cas, PhotoViewHolder) avant d’être utilisé. L’adaptateur charge la ressource d’image dans la vue référencée par la propriété du titulaire de Image la vue et copie le texte de légende dans la vue référencée par la propriété du titulaire de Caption la vue. Cela lie la vue associée à ses données.

Notez qu’il OnBindViewHolder s’agit du code qui traite directement de la structure des données. Dans ce cas, OnBindViewHolder comprend comment mapper la position de l’élément RecyclerView à son élément de données associé dans la source de données. Le mappage est simple dans ce cas, car la position peut être utilisée comme index de tableau dans l’album photo ; Toutefois, des sources de données plus complexes peuvent nécessiter un code supplémentaire pour établir un tel mappage.

ItemCount

La ItemCount méthode retourne le nombre d’éléments dans la collection de données. Dans l’exemple d’application de visionneuse de photos, le nombre d’éléments correspond au nombre de photos dans l’album photo :

public override int ItemCount
{
    get { return mPhotoAlbum.NumPhotos; }
}

Pour plus d’informations sur RecyclerView.Adapter, consultez la référence de la classe RecyclerView.Adapter.

Récapitulatif

L’implémentation résultante RecyclerView de l’exemple d’application photo se compose de MainActivity code qui crée la source de données, le gestionnaire de disposition et l’adaptateur. MainActivity crée l’instance mRecyclerView , instancie la source de données et l’adaptateur, et se connecte au gestionnaire de disposition et à l’adaptateur :

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        mPhotoAlbum = new PhotoAlbum();
        SetContentView (Resource.Layout.Main);
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug in the linear layout manager:
        mLayoutManager = new LinearLayoutManager (this);
        mRecyclerView.SetLayoutManager (mLayoutManager);

        // Plug in my adapter:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
        mRecyclerView.SetAdapter (mAdapter);
    }
}

PhotoViewHolder localise et met en cache les références d’affichage :

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

PhotoAlbumAdapter implémente les trois substitutions de méthode requises :

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;
    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }

    public override RecyclerView.ViewHolder
        OnCreateViewHolder (ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.From (parent.Context).
                    Inflate (Resource.Layout.PhotoCardView, parent, false);
        PhotoViewHolder vh = new PhotoViewHolder (itemView);
        return vh;
    }

    public override void
        OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
    {
        PhotoViewHolder vh = holder as PhotoViewHolder;
        vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);
        vh.Caption.Text = mPhotoAlbum[position].Caption;
    }

    public override int ItemCount
    {
        get { return mPhotoAlbum.NumPhotos; }
    }
}

Lorsque ce code est compilé et exécuté, il crée l’application d’affichage de photos de base, comme illustré dans les captures d’écran suivantes :

Deux captures d’écran de l’application d’affichage de photos avec défilement vertical des cartes photo

Si les ombres ne sont pas dessinées (comme indiqué dans la capture d’écran ci-dessus), modifiez Propriétés/AndroidManifest.xml et ajoutez le paramètre d’attribut suivant à l’élément <application> :

android:hardwareAccelerated="true"

Cette application de base prend uniquement en charge la navigation de l’album photo. Elle ne répond pas aux événements tactiles d’élément, ni ne gère-t-elle les modifications apportées aux données sous-jacentes. Cette fonctionnalité est ajoutée à l’extension de l’exemple RecyclerView.

Modification de LayoutManager

En raison de RecyclerViewsa flexibilité, il est facile de modifier l’application pour utiliser un autre gestionnaire de disposition. Dans l’exemple suivant, il est modifié pour afficher l’album photo avec une disposition de grille qui fait défiler horizontalement plutôt qu’avec une disposition linéaire verticale. Pour ce faire, l’instanciation du gestionnaire de disposition est modifiée pour utiliser les GridLayoutManager éléments suivants :

mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);

Cette modification de code remplace la verticale LinearLayoutManager par une GridLayoutManager grille composée de deux lignes qui défilent dans le sens horizontal. Lorsque vous compilez et réexécutez l’application, vous verrez que les photos sont affichées dans une grille et que le défilement est horizontal plutôt que vertical :

Exemple de capture d’écran de l’application avec défilement horizontal des photos dans une grille

En modifiant une seule ligne de code, il est possible de modifier l’application d’affichage photo pour utiliser une disposition différente avec un comportement différent. Notez que ni le code de l’adaptateur ni le code XML de disposition n’ont dû être modifiés pour modifier le style de disposition.

Dans la rubrique suivante, Extension de l’exemple RecyclerView, cet exemple d’application de base est étendu pour gérer les événements de clic d’élément et mettre à jour RecyclerView lorsque la source de données sous-jacente change.