Esempio di Basic RecyclerView
Per comprendere il funzionamento RecyclerView
in un'applicazione tipica, questo argomento illustra un semplice esempio di codice che usa RecyclerView
per visualizzare una raccolta di foto di grandi dimensioni:
RecyclerViewer usa CardView per implementare ogni elemento fotografico nel RecyclerView
layout. A causa dei RecyclerView
vantaggi delle prestazioni, questa app di esempio è in grado di scorrere rapidamente un'ampia raccolta di foto senza problemi e senza ritardi evidenti.
Un'origine dati di esempio
In questa app di esempio, un'origine dati "album foto" (rappresentata dalla classe ) fornisce RecyclerView
contenuto dell'elementoPhotoAlbum
.
PhotoAlbum
è una raccolta di foto con didascalie; quando si crea un'istanza, si ottiene una collezione pronta per 32 foto:
PhotoAlbum mPhotoAlbum = new PhotoAlbum ();
Ogni istanza di foto in PhotoAlbum
espone le proprietà che consentono di leggere il relativo ID risorsa immagine, PhotoID
e la relativa stringa di didascalia, Caption
. La raccolta di foto è organizzata in modo che ogni foto sia accessibile da un indicizzatore. Ad esempio, le righe di codice seguenti accedono all'ID risorsa immagine e alla didascalia per la decima foto nella raccolta:
int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;
PhotoAlbum
fornisce anche un RandomSwap
metodo che è possibile chiamare per scambiare la prima foto nella raccolta con una foto scelta casualmente altrove nella raccolta:
mPhotoAlbum.RandomSwap ();
Poiché i dettagli di implementazione di PhotoAlbum
non sono rilevanti per comprendere RecyclerView
, il PhotoAlbum
codice sorgente non viene presentato qui.
Layout e inizializzazione
Il file di layout Main.axml è costituito da un singolo RecyclerView
all'interno di un LinearLayout
oggetto :
<?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>
Si noti che è necessario usare il nome completo android.support.v7.widget.RecyclerView perché RecyclerView
è incluso in un pacchetto in una libreria di supporto. Il OnCreate
metodo di MainActivity
inizializza questo layout, crea un'istanza dell'adapter e prepara l'origine dati sottostante:
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);
Il codice effettua quanto segue:
Crea un'istanza dell'origine
PhotoAlbum
dati.Passa l'origine dati dell'album fotografico al costruttore dell'adattatore ,
PhotoAlbumAdapter
definito più avanti in questa guida. Si noti che è considerata una procedura consigliata per passare l'origine dati come parametro al costruttore dell'adattatore.Ottiene l'oggetto
RecyclerView
dal layout.Collega l'adattatore all'istanza
RecyclerView
chiamando ilRecyclerView
SetAdapter
metodo come illustrato in precedenza.
Gestione layout
Ogni elemento in RecyclerView
è costituito da un CardView
oggetto che contiene un'immagine e una didascalia foto (i dettagli sono trattati nella sezione View Holder sotto). Il valore predefinito LinearLayoutManager
viene usato per disporre ognuno di essi CardView
in una disposizione di scorrimento verticale:
mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);
Questo codice risiede nel metodo dell'attività OnCreate
principale. Il costruttore per la gestione layout richiede un contesto, quindi viene MainActivity
passato usando this
come illustrato in precedenza.
Invece di usare il valore predefinito LinearLayoutManager
, è possibile collegare un gestore layout personalizzato che visualizza due CardView
elementi affiancati, implementando un effetto di animazione di rotazione pagina per attraversare la raccolta di foto. Più avanti in questa guida verrà illustrato un esempio di come modificare il layout scambiando in un gestore di layout diverso.
Visualizza supporto
La classe del titolare della vista è denominata PhotoViewHolder
. Ogni PhotoViewHolder
istanza contiene riferimenti a ImageView
e TextView
di un elemento di riga associato, disposto in un CardView
diagramma riportato di seguito:
PhotoViewHolder
deriva da RecyclerView.ViewHolder
e contiene proprietà per archiviare i riferimenti a ImageView
e TextView
visualizzati nel layout precedente.
PhotoViewHolder
è costituito da due proprietà e da un costruttore:
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);
}
}
In questo esempio di codice, il PhotoViewHolder
costruttore viene passato un riferimento alla visualizzazione elemento padre (l'oggetto ) che PhotoViewHolder
esegue il CardView
wrapping. Si noti che la visualizzazione elemento padre viene sempre inoltrata al costruttore di base. Il PhotoViewHolder
costruttore chiama FindViewById
nella visualizzazione elemento padre per individuare rispettivamente i riferimenti ImageView
alla visualizzazione figlio e TextView
, archiviando i risultati nelle Image
proprietà e Caption
. L'adattatore recupera in seguito i riferimenti di visualizzazione da queste proprietà quando aggiorna le CardView
visualizzazioni figlio con nuovi dati.
Per altre informazioni su , vedere le informazioni di riferimento sulla RecyclerView.ViewHolder
classe RecyclerView.ViewHolder.
Adapter
L'adattatore carica ogni RecyclerView
riga con dati per una particolare fotografia. Per una determinata fotografia in corrispondenza della posizione della riga P, ad esempio, l'adattatore individua i dati associati nella posizione P all'interno dell'origine dati e copia questi dati nell'elemento di riga nella posizione P dell'insieme RecyclerView
. L'adattatore utilizza il supporto di visualizzazione per cercare i riferimenti per ImageView
e TextView
in tale posizione in modo che non sia necessario chiamare FindViewById
ripetutamente tali visualizzazioni mentre l'utente scorre la raccolta di fotografie e riutilizza le visualizzazioni.
In RecyclerViewer una classe adapter deriva da RecyclerView.Adapter
per creare PhotoAlbumAdapter
:
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public PhotoAlbum mPhotoAlbum;
public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
{
mPhotoAlbum = photoAlbum;
}
...
}
Il membro contiene l'origine dati (album fotografico) passata al costruttore. Il mPhotoAlbum
costruttore copia l'album fotografico in questa variabile membro. Vengono implementati i metodi obbligatori RecyclerView.Adapter
seguenti:
OnCreateViewHolder
: crea un'istanza del file di layout dell'elemento e del supporto di visualizzazione.OnBindViewHolder
: carica i dati nella posizione specificata nelle visualizzazioni i cui riferimenti vengono archiviati nel supporto di visualizzazione specificato.ItemCount
: restituisce il numero di elementi nell'origine dati.
Gestione layout chiama questi metodi mentre posiziona gli elementi all'interno di RecyclerView
. L'implementazione di questi metodi viene esaminata nelle sezioni seguenti.
OnCreateViewHolder
Gestione layout chiama OnCreateViewHolder
quando è RecyclerView
necessario un nuovo supporto di visualizzazione per rappresentare un elemento. OnCreateViewHolder
gonfia la visualizzazione elemento dal file di layout della visualizzazione ed esegue il wrapping della visualizzazione in una nuova PhotoViewHolder
istanza. Il PhotoViewHolder
costruttore individua e archivia i riferimenti alle visualizzazioni figlio nel layout come descritto in precedenza in View Holder.
Ogni elemento di riga è rappresentato da un CardView
oggetto che contiene ( ImageView
per la foto) e un TextView
(per la didascalia). Questo layout si trova nel file 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>
Questo layout rappresenta un singolo elemento di riga nell'oggetto RecyclerView
. Il OnBindViewHolder
metodo (descritto di seguito) copia i dati dall'origine dati in ImageView
e TextView
di questo layout.
OnCreateViewHolder
gonfia questo layout per una determinata posizione di foto in RecyclerView
e crea un'istanza di una nuova PhotoViewHolder
istanza (che individua e memorizza nella cache i riferimenti alle ImageView
visualizzazioni figlio e TextView
nel layout associato CardView
):
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'istanza del titolare di visualizzazione risultante, vh
, viene restituita al chiamante (gestione layout).
OnBindViewHolder
Quando il gestore layout è pronto per visualizzare una visualizzazione specifica nell'area RecyclerView
dello schermo visibile, chiama il metodo dell'adattatore OnBindViewHolder
per riempire l'elemento nella posizione di riga specificata con contenuto dall'origine dati. OnBindViewHolder
ottiene le informazioni sulla foto per la posizione di riga specificata (la risorsa immagine della foto e la stringa per la didascalia della foto) e copia questi dati nelle visualizzazioni associate. Le visualizzazioni si trovano tramite riferimenti archiviati nell'oggetto del supporto di visualizzazione (che viene passato tramite il holder
parametro ):
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;
}
Prima di usarlo, è necessario eseguire il cast dell'oggetto porta vista passato nel tipo di supporto della vista derivata ( in questo caso , PhotoViewHolder
).
L'adattatore carica la risorsa immagine nella visualizzazione a cui fa riferimento la proprietà del Image
titolare della visualizzazione e copia il testo della didascalia nella vista a cui fa riferimento la proprietà del Caption
titolare della visualizzazione. In questo modo la vista associata viene associata ai relativi dati.
Si noti che OnBindViewHolder
è il codice che gestisce direttamente la struttura dei dati. In questo caso, OnBindViewHolder
viene illustrato come eseguire il mapping della posizione dell'elemento RecyclerView
all'elemento di dati associato nell'origine dati. Il mapping è semplice in questo caso perché la posizione può essere usata come indice di matrice nell'album fotografico; Tuttavia, origini dati più complesse possono richiedere codice aggiuntivo per stabilire tale mapping.
ItemCount
Il ItemCount
metodo restituisce il numero di elementi nella raccolta dati. Nell'app visualizzatore foto di esempio, il conteggio degli elementi è il numero di foto nell'album fotografico:
public override int ItemCount
{
get { return mPhotoAlbum.NumPhotos; }
}
Per altre informazioni su , vedere le informazioni di riferimento sulla RecyclerView.Adapter
classe RecyclerView.Adapter.
Mettere tutto insieme
L'implementazione risultante RecyclerView
per l'app foto di MainActivity
esempio è costituita da codice che crea l'origine dati, il gestore layout e l'adattatore. MainActivity
crea l'istanza mRecyclerView
, crea un'istanza dell'origine dati e dell'adattatore e collega la gestione layout e l'adattatore:
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
individua e memorizza nella cache i riferimenti alla vista:
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
implementa i tre override obbligatori del metodo:
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; }
}
}
Quando questo codice viene compilato ed eseguito, crea l'app di visualizzazione foto di base, come illustrato negli screenshot seguenti:
Se le ombreggiature non vengono disegnate (come illustrato nello screenshot precedente), modificare Proprietà/AndroidManifest.xml e aggiungere l'impostazione dell'attributo seguente all'elemento <application>
:
android:hardwareAccelerated="true"
Questa app di base supporta solo l'esplorazione dell'album fotografico. Non risponde agli eventi di tocco degli elementi, né gestisce le modifiche nei dati sottostanti. Questa funzionalità viene aggiunta in Estensione dell'esempio RecyclerView.
Modifica di LayoutManager
Grazie alla RecyclerView
flessibilità, è facile modificare l'app per usare un gestore di layout diverso. Nell'esempio seguente viene modificato per visualizzare l'album fotografico con un layout griglia che scorre orizzontalmente anziché con un layout lineare verticale. A tale scopo, la creazione di un'istanza di Gestione layout viene modificata in modo da usare come GridLayoutManager
segue:
mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);
Questa modifica del codice sostituisce la verticale LinearLayoutManager
con un oggetto GridLayoutManager
che presenta una griglia costituita da due righe che scorrono nella direzione orizzontale. Quando si compila ed esegue di nuovo l'app, si noterà che le fotografie vengono visualizzate in una griglia e che lo scorrimento è orizzontale anziché verticale:
Modificando una sola riga di codice, è possibile modificare l'app di visualizzazione foto per usare un layout diverso con un comportamento diverso. Si noti che non è stato necessario modificare né il codice dell'adattatore né il codice XML di layout per modificare lo stile di layout.
Nell'argomento successivo, Estensione dell'esempio RecyclerView, questa app di esempio di base viene estesa per gestire gli eventi di clic sugli elementi e aggiornare RecyclerView
quando l'origine dati sottostante cambia.