Podstawowy przykład recyclerView
Aby zrozumieć, jak RecyclerView
działa w typowej aplikacji, w tym temacie przedstawiono prosty przykład kodu, który służy RecyclerView
do wyświetlania dużej kolekcji zdjęć:
Program RecyclerViewer używa kontrolki CardView do implementowania każdego elementu fotografii w układzie RecyclerView
. Ze względu na RecyclerView
zalety wydajności ta przykładowa aplikacja jest w stanie szybko przewijać dużą kolekcję zdjęć płynnie i bez zauważalnych opóźnień.
Przykładowe źródło danych
W tej przykładowej aplikacji źródło danych "album fotograficzny" (reprezentowane przez klasę PhotoAlbum
) dostarcza RecyclerView
zawartość elementu.
PhotoAlbum
jest kolekcją zdjęć z podpisami; gdy utworzysz wystąpienie, uzyskasz gotową kolekcję 32 zdjęć:
PhotoAlbum mPhotoAlbum = new PhotoAlbum ();
Każde wystąpienie zdjęcia w PhotoAlbum
programie uwidacznia właściwości, które umożliwiają odczytywanie identyfikatora zasobu obrazu, PhotoID
i jego ciągu podpisu, Caption
. Kolekcja zdjęć jest zorganizowana tak, że każde zdjęcie może uzyskać dostęp do indeksatora. Na przykład następujące wiersze kodu uzyskują dostęp do identyfikatora zasobu obrazu i podpisu dla dziesiątego zdjęcia w kolekcji:
int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;
PhotoAlbum
Udostępnia również metodę RandomSwap
, którą można wywołać, aby zamienić pierwsze zdjęcie w kolekcji z losowo wybranym zdjęciem w innej części kolekcji:
mPhotoAlbum.RandomSwap ();
Ponieważ szczegóły PhotoAlbum
implementacji nie są istotne dla zrozumienia RecyclerView
, PhotoAlbum
kod źródłowy nie jest tutaj przedstawiony.
Układ i inicjowanie
Plik układu Main.axml składa się z jednego RecyclerView
pliku w obiekcie 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>
Należy pamiętać, że należy użyć w pełni kwalifikowanej nazwy android.support.v7.widget.RecyclerView , ponieważ RecyclerView
jest spakowana w bibliotece pomocy technicznej. Metoda OnCreate
inicjuje MainActivity
ten układ, tworzy wystąpienie karty i przygotowuje bazowe źródło danych:
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);
Ten kod powoduje wykonanie następujących czynności:
PhotoAlbum
Tworzy wystąpienie źródła danych.Przekazuje źródło danych albumu zdjęć do konstruktora adaptera
PhotoAlbumAdapter
(który jest zdefiniowany w dalszej części tego przewodnika). Należy pamiętać, że najlepszym rozwiązaniem jest przekazanie źródła danych jako parametru do konstruktora karty.Pobiera element
RecyclerView
z układu.Podłącza adapter do
RecyclerView
wystąpienia, wywołując metodęRecyclerView
SetAdapter
, jak pokazano powyżej.
Menedżer układu
Każdy element w obiekcie RecyclerView
składa się z elementu zawierającego CardView
zdjęcie i podpis zdjęcia (szczegóły zostały omówione w poniższej sekcji Posiadacz widoku). Wstępnie zdefiniowany LinearLayoutManager
element służy do układania poszczególnych CardView
elementów w układzie przewijania w pionie:
mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);
Ten kod znajduje się w metodzie OnCreate
głównego działania. Konstruktor do menedżera układów wymaga kontekstu, więc MainActivity
element jest przekazywany przy użyciuthis
, jak pokazano powyżej.
Zamiast korzystać ze wstępnie zdefiniowanej LinearLayoutManager
metody , możesz podłączyć niestandardowy menedżer układów, który wyświetla dwa CardView
elementy obok siebie, implementując efekt animacji obracający stronę, aby przejść przez kolekcję zdjęć. W dalszej części tego przewodnika zobaczysz przykład modyfikowania układu, zamieniając się w innym menedżerze układu.
Uchwyt widoku
Klasa uchwytu widoku nosi nazwę PhotoViewHolder
. Każde PhotoViewHolder
wystąpienie zawiera odwołania do ImageView
i TextView
skojarzonego elementu wiersza, który jest rozmieszczony w CardView
diagramie tutaj:
PhotoViewHolder
element pochodzi z RecyclerView.ViewHolder
właściwości i zawiera właściwości do przechowywania odwołań do ImageView
obiektu i TextView
pokazanego w powyższym układzie.
PhotoViewHolder
składa się z dwóch właściwości i jednego konstruktora:
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);
}
}
W tym przykładzie PhotoViewHolder
kodu konstruktor jest przekazywany odwołanie do widoku elementu nadrzędnego () CardView
zawijanego PhotoViewHolder
. Należy pamiętać, że zawsze przekazujesz widok elementu nadrzędnego do konstruktora podstawowego. Konstruktor PhotoViewHolder
wywołuje FindViewById
widok elementu nadrzędnego, aby zlokalizować każde z odwołań do widoku podrzędnego i ImageView
TextView
, przechowując odpowiednio wyniki we Image
właściwościach i Caption
. Karta pobiera później odwołania do widoku z tych właściwości, gdy aktualizuje widoki podrzędne z CardView
nowymi danymi.
Aby uzyskać więcej informacji na temat RecyclerView.ViewHolder
klasy , zobacz dokumentację klasy RecyclerView.ViewHolder.
Adapter
Karta ładuje każdy RecyclerView
wiersz z danymi dla konkretnej fotografii. Dla danego zdjęcia w pozycji wiersza P, na przykład karta lokalizuje skojarzone dane w pozycji P w źródle danych i kopiuje te dane do elementu wiersza w pozycji P w RecyclerView
kolekcji. Adapter używa uchwytu widoku do wyszukiwania odwołań do ImageView
i TextView
w tej pozycji, więc nie musi wielokrotnie wywoływać FindViewById
tych widoków, ponieważ użytkownik przewija kolekcję zdjęć i ponownie używa widoków.
W programie RecyclerViewer klasa adaptera jest pochodna RecyclerView.Adapter
w celu utworzenia elementu PhotoAlbumAdapter
:
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public PhotoAlbum mPhotoAlbum;
public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
{
mPhotoAlbum = photoAlbum;
}
...
}
Element mPhotoAlbum
członkowski zawiera źródło danych (album fotograficzny), które jest przekazywane do konstruktora; konstruktor kopiuje album fotograficzny do tej zmiennej składowej. Zaimplementowano następujące wymagane RecyclerView.Adapter
metody:
OnCreateViewHolder
— tworzy wystąpienie pliku układu elementu i uchwyt widoku.OnBindViewHolder
— Ładuje dane na określonej pozycji do widoków, których odwołania są przechowywane w danym posiadaczu widoku.ItemCount
— zwraca liczbę elementów w źródle danych.
Menedżer układów wywołuje te metody, gdy pozycjonuje elementy w obiekcie RecyclerView
. Implementacja tych metod jest badana w poniższych sekcjach.
OnCreateViewHolder
Menedżer układu wywołuje funkcję OnCreateViewHolder
, gdy RecyclerView
nowy uchwyt widoku musi reprezentować element. OnCreateViewHolder
Zwiększa widok elementu z pliku układu widoku i opakowuje widok w nowym PhotoViewHolder
wystąpieniu. Konstruktor PhotoViewHolder
lokalizuje i przechowuje odwołania do widoków podrzędnych w układzie zgodnie z wcześniejszym opisem w widoku Holder.
Każdy element wiersza jest reprezentowany przez element CardView
zawierający ( ImageView
dla zdjęcia) i TextView
(dla podpisu). Ten układ znajduje się w pliku 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>
Ten układ reprezentuje pojedynczy element wiersza w elemencie RecyclerView
. Metoda (opisana OnBindViewHolder
poniżej) kopiuje dane ze źródła danych do ImageView
i TextView
tego układu.
OnCreateViewHolder
Zwiększa ten układ dla danej lokalizacji zdjęć w RecyclerView
obiekcie i tworzy wystąpienie nowego PhotoViewHolder
wystąpienia (które lokalizuje i buforuje odwołania do ImageView
widoków podrzędnych i i TextView
podrzędnych w skojarzonym CardView
układzie):
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;
}
Wynikowe wystąpienie vh
właściciela widoku , jest zwracane z powrotem do obiektu wywołującego (menedżera układu).
OnBindViewHolder
Gdy menedżer układów jest gotowy do wyświetlenia określonego widoku w RecyclerView
widocznym obszarze ekranu, wywołuje metodę adaptera OnBindViewHolder
, aby wypełnić element na określonej pozycji wiersza zawartością ze źródła danych. OnBindViewHolder
Pobiera informacje o zdjęciu dla określonej pozycji wiersza (zasób obrazu zdjęcia i ciąg podpisu zdjęcia) i kopiuje te dane do skojarzonych widoków. Widoki znajdują się za pośrednictwem odwołań przechowywanych w obiekcie właściciela widoku (który jest przekazywany za pośrednictwem parametru holder
):
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;
}
Przekazany obiekt uchwytu widoku musi najpierw zostać rzutowany do typu pochodnego uchwytu widoku (w tym przypadku PhotoViewHolder
) przed jego zastosowaniem.
Karta ładuje zasób obrazu do widoku, do który odwołuje się właściwość właściciela Image
widoku, i kopiuje tekst podpisu do widoku, do który odwołuje się właściwość właściciela Caption
widoku. Spowoduje to powiązanie skojarzonego widoku z danymi.
Zwróć uwagę, że OnBindViewHolder
jest to kod, który zajmuje się bezpośrednio strukturą danych. W takim przypadku rozumie sposób OnBindViewHolder
mapowania RecyclerView
pozycji elementu na skojarzony element danych w źródle danych. Mapowanie jest w tym przypadku proste, ponieważ pozycja może być używana jako indeks tablicy do albumu fotograficznego; jednak bardziej złożone źródła danych mogą wymagać dodatkowego kodu w celu ustanowienia takiego mapowania.
ItemCount
Metoda ItemCount
zwraca liczbę elementów w kolekcji danych. W przykładowej aplikacji przeglądarki zdjęć liczba elementów to liczba zdjęć w albumie fotograficznym:
public override int ItemCount
{
get { return mPhotoAlbum.NumPhotos; }
}
Aby uzyskać więcej informacji na temat RecyclerView.Adapter
klasy , zobacz dokumentację klasy RecyclerView.Adapter.
Łączenie tego wszystkiego
Wynikowa RecyclerView
implementacja przykładowej aplikacji photo składa się z MainActivity
kodu, który tworzy źródło danych, menedżer układu i kartę. MainActivity
mRecyclerView
Tworzy wystąpienie, tworzy wystąpienie źródła danych i adaptera, a następnie podłącza menedżera układu i adaptera:
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
lokalizuje i buforuje odwołania do widoku:
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
implementuje trzy wymagane przesłonięcia metody:
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; }
}
}
Po skompilowaniu i uruchomieniu tego kodu zostanie utworzona podstawowa aplikacja do wyświetlania zdjęć, jak pokazano na poniższych zrzutach ekranu:
Jeśli cienie nie są rysowane (jak pokazano na powyższym zrzucie ekranu), zmodyfikuj właściwości/AndroidManifest.xml i dodaj następujące ustawienie atrybutu <application>
do elementu:
android:hardwareAccelerated="true"
Ta podstawowa aplikacja obsługuje tylko przeglądanie albumu fotograficznego. Nie reaguje na zdarzenia z obsługą elementów ani nie obsługuje zmian w danych bazowych. Ta funkcja jest dodawana w sekcji Rozszerzanie przykładu recyclerView.
Zmienianie menedżera układu
RecyclerView
Ze względu na elastyczność można łatwo zmodyfikować aplikację tak, aby korzystała z innego menedżera układów. W poniższym przykładzie jest modyfikowany tak, aby wyświetlał album fotograficzny z układem siatki, który przewija się w poziomie, a nie z pionowym układem liniowym. W tym celu wystąpienie menedżera układów jest modyfikowane w następujący GridLayoutManager
sposób:
mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);
Ta zmiana kodu zastępuje pionową LinearLayoutManager
GridLayoutManager
siatkę zawierającą dwie wiersze przewijane w kierunku poziomym. Po ponownym skompilowaniu i uruchomieniu aplikacji zobaczysz, że zdjęcia są wyświetlane w siatce, a przewijanie jest poziome, a nie pionowe:
Zmieniając tylko jeden wiersz kodu, można zmodyfikować aplikację do wyświetlania zdjęć, aby używać innego układu z innym zachowaniem. Zwróć uwagę, że ani kod karty, ani kod XML układu nie musiał być modyfikowany w celu zmiany stylu układu.
W następnym temacie Rozszerzenie przykładu RecyclerView ta podstawowa przykładowa aplikacja jest rozszerzona w celu obsługi zdarzeń kliknięcia elementu i aktualizowania RecyclerView
po zmianie bazowego źródła danych.