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 :
RecyclerViewer utilise CardView pour implémenter chaque élément de photographie dans la RecyclerView
disposition. En raison des avantages de RecyclerView
performances 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, PhotoID
et 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 :
Instancie la source de
PhotoAlbum
données.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.Obtient la
RecyclerView
disposition.Branche l’adaptateur dans l’instance
RecyclerView
en appelant laRecyclerView
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 :
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 etTextView
ImageView
, 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 CardView
vues 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.
OnCreateViewHolder
gonfle 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 vh
retourné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 :
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 RecyclerView
sa 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 :
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.