Erweitern des RecyclerView-Beispiels
Die in A Basic RecyclerView (Beispiel ) beschriebene einfache App macht eigentlich nicht viel – sie führt einfach einen Bildlauf durch und zeigt eine feste Liste von Fotoelementen an, um das Browsen 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 sein Standard. In den folgenden Abschnitten erfahren Sie, wie Sie Elementklickereignisse behandeln und aktualisieren RecyclerView
, wenn sich die zugrunde liegende Datenquelle ändert.
Behandeln von Elementklickereignissen
Wenn ein Benutzer ein Element im RecyclerView
Element berührt, wird ein Elementklickereignis generiert, um die App darüber zu benachrichtigen, welches Element berührt wurde. Dieses Ereignis wird nicht durch – RecyclerView
stattdessen erkennt die Elementansicht (die in den Ansichtshalter eingeschlossen ist) Berührungen und meldet diese Berührungen als Klickereignisse.
Um die Behandlung von Elementklickereignissen zu veranschaulichen, erläutern die folgenden Schritte, wie die grundlegende Fotoanzeige-App geändert wird, um zu melden, welches Foto vom Benutzer berührt wurde. Wenn ein Elementklickereignis in der Beispiel-App auftritt, erfolgt die folgende Sequenz:
Das Foto
CardView
erkennt das Elementklickereignis und benachrichtigt den Adapter.Der Adapter leitet das Ereignis (mit Elementpositionsinformationen) an den Elementklickhandler der Aktivität weiter.
Der Elementklickhandler der Aktivität antwortet auf das Elementklickereignis.
Zunächst wird der Klassendefinition ein aufgerufenes ItemClick
Ereignishandlermemm hinzugefügt PhotoAlbumAdapter
:
public event EventHandler<int> ItemClick;
Als Nächstes wird eine Elementklick-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
. Ein guter Ort, um dies zu tun, ist unmittelbar nach PhotoAlbumAdapter
der Erstellung:
mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;
In diesem grundlegenden Beispiel erfolgt die Handlerregistrierung in der Standard-AktivitätsmethodeOnCreate
, aber eine Produktions-App registriert den Handler möglicherweise in OnResume
und hebt sie auf – weitere Informationen finden Sie im OnPause
Aktivitätslebenszyklus.
PhotoAlbumAdapter
wird jetzt aufgerufen OnItemClick
, wenn es ein Elementklick-Ereignis empfängt. 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 Elementklickereignisse aus Elementansichten. Bevor dieser Listener mit 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 ist der geänderte 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 den CardView
Benutzer, der vom Benutzer berührt wurde. Beachten Sie, dass die Basisklasse des Ansichtshalters die Layoutposition des Elements (CardView
) kennt, das es 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 in der Anzeige dazu, dass ein Popup angezeigt wird, das meldet, welches Foto berührt wurde:
In diesem Beispiel wird nur ein Ansatz für die Implementierung von Ereignishandlern mit RecyclerView
. Ein weiterer Ansatz, der hier verwendet werden könnte, ist das Platzieren von Ereignissen auf dem Sichthalter und das Abonnieren des Adapters für diese Ereignisse. Wenn die Beispielfoto-App eine Fotobearbeitungsfunktion bereitgestellt hat, sind für die ImageView
und die TextView
einzelnen Ereignisse CardView
separate Ereignisse erforderlich: Touches auf dem TextView
Bildschirm würden ein EditView
Dialogfeld starten, mit dem der Benutzer die Untertitel bearbeiten kann, und die Fingereingaben würden ImageView
ein Foto-Touchup-Tool starten, mit dem der Benutzer das Foto zuschneiden oder drehen kann. Je nach den Anforderungen Ihrer App müssen Sie den besten Ansatz für die Behandlung und Reaktion auf Touchereignisse entwerfen.
Um zu veranschaulichen, wie RecyclerView
aktualisiert werden kann, wenn sich das Dataset ändert, kann die Beispielfotoanzeige-App so geändert werden, dass ein Foto in der Datenquelle zufällig ausgewählt und mit dem ersten Foto ausgetauscht wird. Zuerst 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 wird Code am Ende der Methode der Standard Aktivität OnCreate
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 vertauscht ein Foto zufällig mit dem ersten Foto in der Datenquelle und gibt dann den Index des zufällig ausgetauschten 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 Stand 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 wurden zwei Elemente geändert: das erste Foto und das getauschte Foto). Dadurch wird RecyclerView
die Anzeige aktualisiert, 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 "Wahlauswahl " getippt wird, wird die Anzeige aktualisiert, RecyclerView
um anzuzeigen, dass ein Foto in der Sammlung weiter unten mit dem ersten Foto in der Sammlung ausgetauscht wurde:
Es könnte natürlich aufgerufen werden, anstatt die beiden Aufrufe NotifyItemChanged
auszuführen, aber dies würde dazu zwingenRecyclerView
, NotifyDataSetChanged
die gesamte Sammlung zu aktualisieren, obwohl nur zwei Elemente in der Auflistung geändert wurden. Anrufe NotifyItemChanged
sind wesentlich effizienter als Anrufe NotifyDataSetChanged
.