Ein einfaches RecyclerView-Beispiel
Um die Funktionsweise in einer typischen Anwendung zu verstehen RecyclerView
, untersucht dieses Thema ein einfaches Codebeispiel, das zum Anzeigen einer großen Sammlung von Fotos verwendet RecyclerView
wird:
RecyclerViewer verwendet CardView , um jedes Fotoelement im RecyclerView
Layout zu implementieren. Aufgrund der RecyclerView
Leistungsvorteile ist diese Beispiel-App in der Lage, einen schnellen Bildlauf durch eine große Sammlung von Fotos reibungslos und ohne spürbare Verzögerungen zu ermöglichen.
Beispieldatenquelle
In dieser Beispiel-App liefert RecyclerView
eine "Fotoalbum"-Datenquelle (dargestellt durch die PhotoAlbum
Klasse) Elementinhalte.
PhotoAlbum
ist eine Sammlung von Fotos mit Beschriftungen; Wenn Sie es instanziieren, erhalten Sie eine vorgefertigte Sammlung von 32 Fotos:
PhotoAlbum mPhotoAlbum = new PhotoAlbum ();
Jede Fotoinstanz in PhotoAlbum
macht Eigenschaften verfügbar, mit denen Sie die Bildressourcen-ID PhotoID
und die Beschriftungszeichenfolge Caption
lesen können. Die Sammlung von Fotos ist so organisiert, dass auf jedes Foto von einem Indexer zugegriffen werden kann. Die folgenden Codezeilen greifen beispielsweise auf die Bildressourcen-ID und die Beschriftung für das zehnte Foto in der Auflistung zu:
int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;
PhotoAlbum
Stellt außerdem eine RandomSwap
Methode bereit, mit der Sie das erste Foto in der Sammlung mit einem zufällig ausgewählten Foto an anderer Stelle in der Sammlung austauschen können:
mPhotoAlbum.RandomSwap ();
Da die Implementierungsdetails PhotoAlbum
für das Verständnis RecyclerView
nicht relevant sind, wird der PhotoAlbum
Quellcode hier nicht dargestellt.
Layout und Initialisierung
Die Layoutdatei " Main.axml" besteht aus einem einzelnen RecyclerView
in einem 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>
Beachten Sie, dass Sie den vollqualifizierten Namen "android.support.v7.widget.RecyclerView " verwenden müssen, da RecyclerView
es in einer Supportbibliothek verpackt ist. Die OnCreate
Methode der MainActivity
Initialisierung dieses Layouts, instanziiert den Adapter und bereitet die zugrunde liegende Datenquelle vor:
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);
Dieser Code bewirkt Folgendes:
Instanziiert die
PhotoAlbum
Datenquelle.Übergibt die Fotoalbumdatenquelle an den Konstruktor des Adapters
PhotoAlbumAdapter
(die weiter unten in dieser Anleitung definiert ist). Beachten Sie, dass es als bewährte Methode gilt, die Datenquelle als Parameter an den Konstruktor des Adapters zu übergeben.Ruft das
RecyclerView
Layout ab.Plugs the adapter into the
RecyclerView
instance by calling theRecyclerView
SetAdapter
method as shown above.
Layout-Manager
Jedes Element besteht RecyclerView
aus einem CardView
Element, das ein Fotobild und eine Fotobeschriftung enthält (Details werden im Abschnitt "Ansichtshalter " unten behandelt). Das vordefinierte Layout LinearLayoutManager
wird verwendet, um jede CardView
in einer vertikalen Bildlaufanordnung zu gestalten:
mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);
Dieser Code befindet sich in der Methode der Hauptaktivität OnCreate
. Der Konstruktor für den Layout-Manager erfordert einen Kontext, sodass der MainActivity
Konstruktor wie this
oben dargestellt übergeben wird.
Anstatt die vordefinierten LinearLayoutManager
Elemente zu verwenden, können Sie einen benutzerdefinierten Layout-Manager anschließen, der zwei CardView
Elemente nebeneinander anzeigt und einen Seitendrehanimationseffekt implementiert, um die Sammlung von Fotos zu durchlaufen. Später in dieser Anleitung sehen Sie ein Beispiel für das Ändern des Layouts, indem Sie in einem anderen Layout-Manager wechseln.
Ansichtshalter
Die Ansichtshalterklasse wird aufgerufen PhotoViewHolder
. Jede PhotoViewHolder
Instanz enthält Verweise auf das ImageView
und TextView
ein zugeordnetes Zeilenelement, das in einem CardView
hier dargestellten Diagramm angeordnet ist:
PhotoViewHolder
abgeleitet von RecyclerView.ViewHolder
und enthält Eigenschaften zum Speichern von Verweisen auf das ImageView
oben gezeigte Layout TextView
.
PhotoViewHolder
besteht aus zwei Eigenschaften und einem Konstruktor:
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 diesem Codebeispiel wird der PhotoViewHolder
Konstruktor einen Verweis auf die übergeordnete Elementansicht (die ) übergeben, PhotoViewHolder
die CardView
umbrochen wird. Beachten Sie, dass Sie die übergeordnete Elementansicht immer an den Basiskonstruktor weiterleiten. Der PhotoViewHolder
Konstruktor ruft FindViewById
die übergeordnete Elementansicht auf, um die einzelnen untergeordneten Ansichtsverweise zu finden, ImageView
und TextView
speichert die Ergebnisse in den Image
jeweiligen Eigenschaften.Caption
Der Adapter ruft später Ansichtsverweise von diesen Eigenschaften ab, wenn diese untergeordneten Ansichten mit neuen Daten aktualisiert CardView
werden.
Weitere Informationen RecyclerView.ViewHolder
finden Sie in der RecyclerView.ViewHolder-Klassenreferenz.
Adapter
Der Adapter lädt jede RecyclerView
Zeile mit Daten für ein bestimmtes Foto. Bei einem bestimmten Foto an Zeilenposition P sucht der Adapter beispielsweise die zugeordneten Daten an Position P innerhalb der Datenquelle und kopiert diese Daten an position P in das Zeilenelement an Position P in der RecyclerView
Auflistung. Der Adapter verwendet den Ansichtshalter, um die Verweise für die ImageView
und TextView
an dieser Position nachzuschlagen, damit diese Ansichten nicht wiederholt aufgerufen FindViewById
werden müssen, während der Benutzer durch die Fotosammlung scrollt und Ansichten wiederverwendet.
In RecyclerViewer wird eine Adapterklasse zum Erstellen PhotoAlbumAdapter
abgeleitetRecyclerView.Adapter
:
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public PhotoAlbum mPhotoAlbum;
public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
{
mPhotoAlbum = photoAlbum;
}
...
}
Das mPhotoAlbum
Element enthält die Datenquelle (das Fotoalbum), die an den Konstruktor übergeben wird. Der Konstruktor kopiert das Fotoalbum in diese Membervariable. Die folgenden erforderlichen RecyclerView.Adapter
Methoden werden implementiert:
OnCreateViewHolder
– Instanziiert die Elementlayoutdatei und den Ansichtshalter.OnBindViewHolder
– Lädt die Daten an der angegebenen Position in die Ansichten, deren Verweise im angegebenen Ansichtshalter gespeichert sind.ItemCount
– Gibt die Anzahl der Elemente in der Datenquelle zurück.
Der Layout-Manager ruft diese Methoden auf, während elemente innerhalb des RecyclerView
Layout-Managers positioniert werden. Die Umsetzung dieser Methoden wird in den folgenden Abschnitten untersucht.
OnCreateViewHolder
Der Layout-Manager ruft auf OnCreateViewHolder
, wenn der RecyclerView
neue Ansichtshalter ein Element darstellt. OnCreateViewHolder
Überbläht die Elementansicht aus der Layoutdatei der Ansicht und umschließt die Ansicht in einer neuen PhotoViewHolder
Instanz. Der PhotoViewHolder
Konstruktor sucht und speichert Verweise auf untergeordnete Ansichten im Layout, wie zuvor in View Holder beschrieben.
Jedes Zeilenelement wird durch ein CardView
Element dargestellt, das ein ImageView
(für das Foto) und ein TextView
(für die Beschriftung) enthält. Dieses Layout befindet sich in der Datei 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>
Dieses Layout stellt ein einzelnes Zeilenelement in der RecyclerView
. Die OnBindViewHolder
Methode (unten beschrieben) kopiert Daten aus der Datenquelle in das ImageView
und TextView
dieses Layout.
OnCreateViewHolder
überhöht dieses Layout für eine bestimmte Fotoposition in der RecyclerView
und instanziiert eine neue PhotoViewHolder
Instanz (die Verweise auf die ImageView
und TextView
untergeordneten Ansichten im zugehörigen CardView
Layout findet und zwischenspeichert):
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;
}
Die resultierende Ansichtshalterinstanz , vh
wird zurück an den Aufrufer (der Layout-Manager) zurückgegeben.
OnBindViewHolder
Wenn der Layout-Manager bereit ist, eine bestimmte Ansicht im RecyclerView
sichtbaren Bildschirmbereich anzuzeigen, ruft er die Methode des Adapters OnBindViewHolder
auf, um das Element an der angegebenen Zeilenposition mit Inhalt aus der Datenquelle auszufüllen. OnBindViewHolder
ruft die Fotoinformationen für die angegebene Zeilenposition (bildressource des Fotos und die Zeichenfolge für die Beschriftung des Fotos) ab und kopiert diese Daten in die zugehörigen Ansichten. Ansichten befinden sich über Verweise, die im Ansichtshalterobjekt gespeichert sind (die über den holder
Parameter übergeben werden):
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;
}
Das übergebene Ansichtshalterobjekt muss zuerst in den abgeleiteten Ansichtshaltertyp (in diesem Fall) umgewandelt werden, PhotoViewHolder
bevor es verwendet wird.
Der Adapter lädt die Bildressource in die Ansicht, auf die von der Eigenschaft des Ansichtsinhabers verwiesen wird, und kopiert den Beschriftungstext Image
in die Ansicht, auf die von der Eigenschaft des Ansichtsinhabers Caption
verwiesen wird. Dadurch wird die zugeordnete Ansicht mit ihren Daten gebunden.
Beachten Sie, dass OnBindViewHolder
es sich um den Code handelt, der sich direkt mit der Struktur der Daten befasst. In diesem Fall wird erläutert, OnBindViewHolder
wie die RecyclerView
Elementposition dem zugeordneten Datenelement in der Datenquelle zugeordnet wird. Die Zuordnung ist in diesem Fall einfach, da die Position als Arrayindex in das Fotoalbum verwendet werden kann; Komplexere Datenquellen erfordern jedoch möglicherweise zusätzlichen Code, um eine solche Zuordnung herzustellen.
ItemCount
Die ItemCount
Methode gibt die Anzahl der Elemente in der Datensammlung zurück. In der Beispiel-Fotoanzeige-App ist die Elementanzahl die Anzahl der Fotos im Fotoalbum:
public override int ItemCount
{
get { return mPhotoAlbum.NumPhotos; }
}
Weitere Informationen RecyclerView.Adapter
finden Sie in der Referenz zur RecyclerView.Adapter-Klasse.
Zusammenfassung
Die resultierende RecyclerView
Implementierung für die Beispielfoto-App besteht aus MainActivity
Code, der die Datenquelle, den Layout-Manager und den Adapter erstellt. MainActivity
erstellt die Instanz, instanziiert die mRecyclerView
Datenquelle und den Adapter und plugs in den Layout-Manager und Adapter:
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
sucht und speichert die Ansichtsverweise zwischen:
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
implementiert die drei erforderlichen Methodenüberschreibungen:
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; }
}
}
Wenn dieser Code kompiliert und ausgeführt wird, wird die einfache Fotoanzeige-App erstellt, wie in den folgenden Screenshots gezeigt:
Wenn Schatten nicht gezeichnet werden (wie im obigen Screenshot dargestellt), bearbeiten Sie Eigenschaften/AndroidManifest.xml , und fügen Sie dem <application>
Element die folgende Attributeinstellung hinzu:
android:hardwareAccelerated="true"
Diese einfache App unterstützt nur das Durchsuchen des Fotoalbums. Es reagiert nicht auf Ereignisse mit Elementeingabe und behandelt keine Änderungen in den zugrunde liegenden Daten. Diese Funktionalität wird im Beispiel zum Erweitern des RecyclerView-Beispiels hinzugefügt.
Ändern des LayoutManagers
Aufgrund der RecyclerView
Flexibilität ist es einfach, die App so zu ändern, dass sie einen anderen Layout-Manager verwendet. Im folgenden Beispiel wird es so geändert, dass das Fotoalbum mit einem Rasterlayout angezeigt wird, das horizontal und nicht mit einem vertikalen linearen Layout scrollt. Dazu wird die Instanziierung des Layout-Managers so geändert, dass sie wie GridLayoutManager
folgt verwendet wird:
mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);
Diese Codeänderung ersetzt die Vertikale LinearLayoutManager
durch ein GridLayoutManager
Raster, das aus zwei Zeilen besteht, die in horizontaler Richtung scrollen. Wenn Sie die App erneut kompilieren und ausführen, sehen Sie, dass die Fotos in einem Raster angezeigt werden und dass der Bildlauf horizontal und nicht vertikal ist:
Durch Das Ändern einer Codezeile ist es möglich, die Fotoanzeige-App so zu ändern, dass ein anderes Layout mit unterschiedlichem Verhalten verwendet wird. Beachten Sie, dass weder der Adaptercode noch die Layout-XML geändert werden mussten, um die Layoutformatvorlage zu ändern.
Im nächsten Thema wird diese einfache Beispiel-App erweitert, um Elementklickereignisse zu behandeln und zu aktualisierenRecyclerView
, wenn sich die zugrunde liegende Datenquelle ändert.