Udostępnij za pośrednictwem


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ęć:

Dwa zrzuty ekranu aplikacji RecyclerView korzystającej z elementów CardView do wyświetlania zdjęć

Program RecyclerViewer używa kontrolki CardView do implementowania każdego elementu fotografii w układzie RecyclerView . Ze względu na RecyclerViewzalety 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, PhotoIDi 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:

  1. PhotoAlbum Tworzy wystąpienie źródła danych.

  2. 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.

  3. Pobiera element RecyclerView z układu.

  4. 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 LinearLayoutManagermetody , 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:

Diagram elementu CardView zawierający element ImageView i TextView

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 () CardViewzawijanego 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 CardViewnowymi danymi.

Aby uzyskać więcej informacji na temat RecyclerView.ViewHolderklasy , 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 vhwł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 RecyclerViewwidocznym 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.Adapterklasy , 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ę. MainActivitymRecyclerView 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:

Dwa zrzuty ekranu aplikacji do wyświetlania zdjęć z pionowo przewijanymi kartami fotograficznymi

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

RecyclerViewZe 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:

Przykładowy zrzut ekranu aplikacji z przewijanymi w poziomie zdjęciami w siatce

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.