Erweitern des RecyclerView-Beispiels
Die in A Basic RecyclerView Example beschriebene einfache App macht eigentlich nicht viel – sie scrollt einfach und zeigt eine feste Liste von Fotoelementen an, um das Durchsuchen zu erleichtern. In realen Anwendungen erwarten Benutzer, dass sie mit der App interagieren können, indem sie auf Elemente in der Anzeige tippen. Außerdem kann sich die zugrunde liegende Datenquelle ändern (oder von der App geändert werden), und der Inhalt der Anzeige muss mit diesen Änderungen konsistent bleiben. In den folgenden Abschnitten erfahren Sie, wie Sie Item-Click-Ereignisse behandeln und aktualisieren RecyclerView
, wenn sich die zugrunde liegende Datenquelle ändert.
Behandeln von Item-Click Ereignissen
Wenn ein Benutzer ein Element im RecyclerView
berührt, wird ein Elementklickereignis generiert, um die App darüber zu informieren, welches Element berührt wurde. Dieses Ereignis wird nicht von RecyclerView
generiert. Stattdessen erkennt die Elementansicht (die im Ansichtshalter umschlossen ist) Berührungen und meldet diese Berührungen als Klickereignisse.
Zur Veranschaulichung der Behandlung von Elementklickereignissen wird in den folgenden Schritten erläutert, wie die einfache Fotoanzeige-App geändert wird, um zu melden, welches Foto vom Benutzer berührt wurde. Wenn in der Beispiel-App ein Elementklickereignis auftritt, erfolgt die folgende Sequenz:
Das Foto
CardView
erkennt das Item-Click-Ereignis und benachrichtigt den Adapter.Der Adapter leitet das Ereignis (mit Elementpositionsinformationen) an den Item-Click-Handler der Aktivität weiter.
Der Item-Click-Handler der Aktivität antwortet auf das Item-Click-Ereignis.
Zunächst wird der PhotoAlbumAdapter
Klassendefinition ein Ereignishandlermember namens ItemClick
hinzugefügt:
public event EventHandler<int> ItemClick;
Als Nächstes wird eine Item-Click-Ereignishandlermethode hinzugefügt.MainActivity
Dieser Handler zeigt kurz ein Popup an, das angibt, welches Fotoelement berührt wurde:
void OnItemClick (object sender, int position)
{
int photoNum = position + 1;
Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
}
Als Nächstes ist eine Codezeile erforderlich, um den OnItemClick
Handler bei PhotoAlbumAdapter
zu registrieren. Ein guter Ort, um dies zu tun, ist sofort nach der PhotoAlbumAdapter
Erstellung:
mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;
In diesem einfachen Beispiel erfolgt die Handlerregistrierung in der Methode der Standard AktivitätOnCreate
, aber eine Produktions-App kann den Handler in OnResume
registrieren und die Registrierung in aufheben. Weitere Informationen finden Sie unter OnPause
Aktivitätslebenszyklus.
PhotoAlbumAdapter
ruft nun auf OnItemClick
, wenn ein Elementklickereignis empfangen wird. Der nächste Schritt besteht darin, einen Handler im Adapter zu erstellen, der dieses ItemClick
Ereignis auslöst. Die folgende Methode wird OnClick
unmittelbar nach der -Methode des Adapters ItemCount
hinzugefügt:
void OnClick (int position)
{
if (ItemClick != null)
ItemClick (this, position);
}
Diese OnClick
Methode ist der Listener des Adapters für Item-Click-Ereignisse aus Elementansichten. Bevor dieser Listener bei einer Elementansicht (über den Ansichtshalter der Elementansicht) registriert werden kann, muss der PhotoViewHolder
Konstruktor geändert werden, um diese Methode als zusätzliches Argument zu akzeptieren und sich beim Elementansichtsereignis Click
zu registrierenOnClick
.
Hier sehen Sie den geänderten PhotoViewHolder
Konstruktor:
public PhotoViewHolder (View itemView, Action<int> listener)
: base (itemView)
{
Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
itemView.Click += (sender, e) => listener (base.LayoutPosition);
}
Der itemView
Parameter enthält einen Verweis auf die , die CardView
vom Benutzer berührt wurde. Beachten Sie, dass die Basisklasse des Ansichtshalters die Layoutposition des Elements (CardView
) kennt, das sie darstellt (über die LayoutPosition
-Eigenschaft), und diese Position wird an die -Methode des Adapters OnClick
übergeben, wenn ein Elementklickereignis stattfindet. Die -Methode des Adapters OnCreateViewHolder
wird geändert, um die -Methode des Adapters OnClick
an den Konstruktor des Ansichtshalters zu übergeben:
PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick);
Wenn Sie nun die Beispiel-Fotoanzeige-App erstellen und ausführen, führt das Tippen auf ein Foto im Display dazu, dass ein Popup angezeigt wird, das meldet, welches Foto berührt wurde:
In diesem Beispiel wird nur ein Ansatz zum Implementieren von Ereignishandlern mit RecyclerView
veranschaulicht. Ein weiterer Ansatz, der hier verwendet werden könnte, ist das Platzieren von Ereignissen auf dem Ansichtshalter und das Abonnieren dieser Ereignisse durch den Adapter. Wenn die Beispielfoto-App eine Fotobearbeitungsfunktion bereitstellt, wären separate Ereignisse für und ImageView
in TextView
jedem CardView
erforderlich: Touchvorgänge auf der TextView
würden ein EditView
Dialogfeld starten, in dem der Benutzer die Untertitel bearbeiten kann, und touchiert auf, ImageView
um ein Foto-Touchup-Tool zu starten, mit dem der Benutzer das Foto zuschneiden oder drehen kann. Abhängig von den Anforderungen Ihrer App müssen Sie den besten Ansatz für die Behandlung und Reaktion auf Touchereignisse entwerfen.
Um zu veranschaulichen, wie aktualisiert werden kann, wenn sich das Dataset ändert, kann die Beispiel-Fotoanzeige-App so geändert werden, dass RecyclerView
ein Foto in der Datenquelle zufällig ausgewählt und mit dem ersten Foto ausgetauscht wird. Zunächst wird dem Main.axml-Layout der Beispielfoto-App eine Schaltfläche "Zufällige Auswahl" hinzugefügt:
<?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">
<Button
android:id="@+id/randPickButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Random Pick" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:scrollbars="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Als Nächstes OnCreate
wird am Ende der Methode der Standard Aktivität Code hinzugefügt, um die Random Pick
Schaltfläche im Layout zu suchen und einen Handler an sie anzufügen:
Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);
randomPickBtn.Click += delegate
{
if (mPhotoAlbum != null)
{
// Randomly swap a photo with the first photo:
int idx = mPhotoAlbum.RandomSwap();
}
};
Dieser Handler ruft die -Methode des Fotoalbums RandomSwap
auf, wenn auf die Schaltfläche "Zufällige Auswahl " getippt wird. Die RandomSwap
-Methode tauscht zufällig ein Foto mit dem ersten Foto in der Datenquelle und gibt dann den Index des zufällig getauschten Fotos zurück. Wenn Sie die Beispiel-App mit diesem Code kompilieren und ausführen, führt das Tippen auf die Schaltfläche "Zufällige Auswahl " nicht zu einer Anzeigeänderung, da die RecyclerView
Änderung an der Datenquelle nicht bekannt ist.
Um nach Änderungen der Datenquelle auf dem Neuesten zu bleiben RecyclerView
, muss der Klickhandler für die Zufällige Auswahl geändert werden, um die Methode des Adapters NotifyItemChanged
für jedes Element in der Auflistung aufzurufen, das geändert wurde (in diesem Fall haben sich zwei Elemente geändert: das erste Foto und das getauschte Foto). Dies führt dazu RecyclerView
, dass die Anzeige aktualisiert wird, sodass sie mit dem neuen Zustand der Datenquelle konsistent ist:
Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);
randomPickBtn.Click += delegate
{
if (mPhotoAlbum != null)
{
int idx = mPhotoAlbum.RandomSwap();
// First photo has changed:
mAdapter.NotifyItemChanged(0);
// Swapped photo has changed:
mAdapter.NotifyItemChanged(idx);
}
};
Wenn nun auf die Schaltfläche Zufällige Auswahl getippt wird, wird die Anzeige aktualisiert, RecyclerView
um anzuzeigen, dass ein Foto weiter unten in der Sammlung mit dem ersten Foto in der Sammlung getauscht wurde:
Natürlich hätte aufgerufen werden können, anstatt die beiden Aufrufe von zu NotifyItemChanged
tätigen, aber dies würde erzwingenRecyclerView
, NotifyDataSetChanged
die gesamte Auflistung zu aktualisieren, obwohl nur zwei Elemente in der Auflistung geändert wurden. Das Aufrufen NotifyItemChanged
von ist deutlich effizienter als das Aufrufen von NotifyDataSetChanged
.