Udostępnij za pośrednictwem


Rozszerzanie przykładu recyclerView

Podstawowa aplikacja opisana w przykładzie Podstawowego recyclerView nie robi zbyt wiele — po prostu przewija i wyświetla stałą listę elementów fotografii, aby ułatwić przeglądanie. W rzeczywistych aplikacjach użytkownicy oczekują, że będą mogli wchodzić w interakcję z aplikacją, naciskając elementy na ekranie. Ponadto bazowe źródło danych może ulec zmianie (lub zmienić przez aplikację), a zawartość ekranu musi pozostać spójna z tymi zmianami. W poniższych sekcjach dowiesz się, jak obsługiwać zdarzenia kliknięcia elementu i aktualizować je po zmianie RecyclerView bazowego źródła danych.

Obsługa zdarzeń kliknięcia elementu

Gdy użytkownik dotknie elementu w elemencie RecyclerView, zostanie wygenerowane zdarzenie kliknięcia elementu, aby powiadomić aplikację o tym, który element został dotknięty. To zdarzenie nie jest generowane przez RecyclerView — zamiast tego widok elementu (który jest opakowany w uchwyt widoku) wykrywa dotknięcia i zgłasza te dotknięcia jako zdarzenia kliknięcia.

Aby zilustrować sposób obsługi zdarzeń kliknięcia elementu, poniższe kroki wyjaśniają, jak podstawowa aplikacja do wyświetlania zdjęć została zmodyfikowana w celu raportowania, które zdjęcie zostało poruszone przez użytkownika. Po wystąpieniu zdarzenia kliknięcia elementu w przykładowej aplikacji następuje następująca sekwencja:

  1. CardView Zdjęcie wykrywa zdarzenie kliknięcia elementu i powiadamia kartę.

  2. Adapter przekazuje zdarzenie (z informacjami o pozycji elementu) do programu obsługi elementów kliknij działanie.

  3. Procedura obsługi kliknięcia elementu działania odpowiada na zdarzenie kliknięcia elementu.

Najpierw element członkowski procedury obsługi zdarzeń o nazwie ItemClick jest dodawany do PhotoAlbumAdapter definicji klasy:

public event EventHandler<int> ItemClick;

Następnie metoda obsługi zdarzeń kliknięcia elementu zostanie dodana do MainActivityelementu . Ten program obsługi krótko wyświetla wyskakujący wyskakujący element, który wskazuje, który element fotografii został dotknięty:

void OnItemClick (object sender, int position)
{
    int photoNum = position + 1;
    Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
}

Następnie potrzebny jest wiersz kodu do zarejestrowania programu obsługi za OnItemClick pomocą PhotoAlbumAdapterpolecenia . Dobrym miejscem do wykonania jest natychmiast po PhotoAlbumAdapter utworzeniu:

mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;

W tym podstawowym przykładzie rejestracja programu obsługi odbywa się w metodzie głównej działania, ale aplikacja produkcyjna może zarejestrować program obsługi i wyrejestrowyć go w OnPause OnResume programie — zobacz Cykl życia działaniaOnCreate, aby uzyskać więcej informacji.

PhotoAlbumAdapter Funkcja będzie teraz wywoływana OnItemClick po odebraniu zdarzenia kliknięcia elementu. Następnym krokiem jest utworzenie procedury obsługi w adapterze, która zgłasza to ItemClick zdarzenie. Następująca metoda, OnClick, jest dodawana natychmiast po metodzie adaptera ItemCount :

void OnClick (int position)
{
    if (ItemClick != null)
        ItemClick (this, position);
}

Ta OnClick metoda jest odbiornikiem adaptera dla zdarzeń kliknięcia elementu z widoków elementów. Przed zarejestrowaniem tego odbiornika w widoku elementu (za pośrednictwem uchwytu widoku elementu) należy zmodyfikować konstruktor, PhotoViewHolder aby akceptował tę metodę jako dodatkowy argument i zarejestrował się OnClick w zdarzeniu widoku Click elementu. Oto zmodyfikowany 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);
}

Parametr itemView zawiera odwołanie do CardView tego, którego dotyczył użytkownik. Należy pamiętać, że klasa bazowa uchwytu widoku zna położenie elementu (), który reprezentuje (CardViewza pośrednictwem LayoutPosition właściwości), a ta pozycja jest przekazywana do metody adaptera OnClick po wystąpieniu zdarzenia kliknięcia elementu. Metoda adaptera OnCreateViewHolder jest modyfikowana w celu przekazania metody adaptera OnClick do konstruktora uchwytu widoku:

PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick);

Teraz, gdy skompilujesz i uruchomisz przykładową aplikację do wyświetlania zdjęć, naciśnięcie zdjęcia na ekranie spowoduje wyświetlenie wyskakujących wyskakujących raportów, które zdjęcie zostało poruszone:

Przykładowy wyskakujący wyświetlany po naciśnięciu karty zdjęcia

W tym przykładzie pokazano tylko jedno podejście do implementowania procedur obsługi zdarzeń za pomocą polecenia RecyclerView. Innym podejściem, którego można użyć w tym miejscu, jest umieszczenie zdarzeń na posiadaczu widoku i subskrybowanie tych zdarzeń przez kartę. Jeśli przykładowa aplikacja do zdjęć dostarczyła możliwość edytowania zdjęć, oddzielne zdarzenia będą wymagane dla ImageView elementu i TextView w obrębie TextView każdego CardViewelementu : spowoduje uruchomienie EditView okna dialogowego umożliwiającego użytkownikowi edytowanie podpis i dotknięcie ImageView spowoduje uruchomienie narzędzia do obsługi przydzieleń zdjęć, które pozwala użytkownikowi przycinać lub obracać zdjęcie. W zależności od potrzeb aplikacji należy zaprojektować najlepsze podejście do obsługi zdarzeń dotykowych i reagowania na nie.

Aby zademonstrować, jak RecyclerView można zaktualizować po zmianie zestawu danych, przykładowa aplikacja do wyświetlania zdjęć może zostać zmodyfikowana w celu losowego wybrania zdjęcia w źródle danych i zamiany jej na pierwsze zdjęcie. Najpierw do przykładowego układu Main.axml aplikacji zdjęć jest dodawany przycisk Wyboru losowego:

<?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>

Następnie kod zostanie dodany na końcu metody działania OnCreate głównego, aby zlokalizować Random Pick przycisk w układzie i dołączyć do niego procedurę obsługi:

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();
    }
};

Ta procedura obsługi wywołuje metodę albumu RandomSwap fotograficznego po naciśnięciu przycisku Losowe wybieranie . Metoda RandomSwap losowo zamienia zdjęcie z pierwszym zdjęciem w źródle danych, a następnie zwraca indeks losowo zamienionego zdjęcia. Po skompilowaniu i uruchomieniu przykładowej aplikacji za pomocą tego kodu naciśnięcie przycisku Wyboru losowego nie spowoduje zmiany wyświetlania, ponieważ RecyclerView nie wiadomo o zmianie źródła danych.

Aby zachować RecyclerView aktualizację po zmianie źródła danych, należy zmodyfikować procedurę obsługi klikania losowego, aby wywołać metodę karty NotifyItemChanged dla każdego elementu w kolekcji, który uległ zmianie (w tym przypadku zmieniono dwa elementy: pierwsze zdjęcie i zamienione zdjęcie). RecyclerView Powoduje to zaktualizowanie jego wyświetlania w taki sposób, aby był zgodny z nowym stanem źródła danych:

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);
    }
};

Teraz po naciśnięciu przycisku Losowe wybieranie aktualizuje ekran, aby pokazać, RecyclerView że zdjęcie w dalszej części kolekcji zostało zamienione na pierwsze zdjęcie w kolekcji:

Pierwszy zrzut ekranu przed zamianą, drugi zrzut ekranu po zamianie

Oczywiście NotifyDataSetChanged można było wywołać metodę zamiast wykonywać dwa wywołania metody NotifyItemChanged, ale wymusiłoby RecyclerView to odświeżenie całej kolekcji, mimo że tylko dwa elementy w kolekcji uległy zmianie. Wywoływanie NotifyItemChanged jest znacznie bardziej wydajne niż wywoływanie metody NotifyDataSetChanged.