Sdílet prostřednictvím


Příklad základního objektu RecyclerView

Abyste pochopili, jak RecyclerView funguje v typické aplikaci, toto téma zkoumá jednoduchý příklad kódu, který používá RecyclerView k zobrazení velké kolekce fotek:

Dva snímky obrazovky aplikace RecyclerView, která k zobrazení fotek používá CardViews

RecyclerViewer používá CardView k implementaci každé položky fotografie v RecyclerView rozložení. RecyclerViewVzhledem k výhodám výkonu je tato ukázková aplikace schopná rychle procházet velkou kolekci fotek hladce a bez znatelných zpoždění.

Příklad zdroje dat

V této ukázkové aplikaci zdroj dat "fotoalbum" (reprezentovaný PhotoAlbum třídou) dodává RecyclerView obsah položky. PhotoAlbum je kolekce fotek s titulky; když vytvoříte instanci, získáte připravenou kolekci 32 fotek:

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

Každá instance fotografie ve PhotoAlbum vlastnostech zveřejňuje vlastnosti, které umožňují číst ID PhotoIDprostředku obrázku a jeho řetězec titulku, Caption. Kolekce fotek je uspořádaná tak, aby každá fotka byla přístupná indexerem. Například následující řádky kódu přistupuje k ID prostředku obrázku a popisku desáté fotky v kolekci:

int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;

PhotoAlbum také poskytuje metodu RandomSwap , kterou můžete volat k prohození první fotky v kolekci s náhodně zvolenou fotkou jinde v kolekci:

mPhotoAlbum.RandomSwap ();

Vzhledem k tomu, že podrobnosti implementace PhotoAlbum nejsou relevantní pro pochopení RecyclerView, PhotoAlbum zdrojový kód zde není uveden.

Rozložení a inicializace

Soubor rozložení Main.axml se skládá z jednoho RecyclerView souboru v rámci 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>

Všimněte si, že musíte použít plně kvalifikovaný název android.support.v7.widget.RecyclerView , protože RecyclerView je zabalený v knihovně podpory. Metoda OnCreate MainActivity inicializuje toto rozložení, vytvoří instanci adaptéru a připraví podkladový zdroj dat:

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

Tento kód provádí následující úkony:

  1. Vytvoří PhotoAlbum instanci zdroje dat.

  2. Předá zdroj dat fotoalba konstruktor adaptéru PhotoAlbumAdapter (který je definován dále v této příručce). Všimněte si, že se považuje za osvědčený postup předání zdroje dat jako parametr konstruktoru adaptéru.

  3. RecyclerView Získá z rozložení.

  4. Připojí adaptér k RecyclerView instanci voláním RecyclerView SetAdapter metody, jak je znázorněno výše.

Správce rozložení

Každá položka v souboru RecyclerView se skládá z CardView obrázku fotky a titulku fotografie (podrobnosti jsou popsány v části Držitel zobrazení níže). Předdefinované LinearLayoutManager se používá k rozložení každého CardView ve svislém uspořádání posouvání:

mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);

Tento kód se nachází v metodě hlavní aktivity OnCreate . Konstruktor pro správce rozložení vyžaduje kontext, takže se MainActivity předává pomocí výše this uvedeného příkladu.

Místo použití předdefinovaného LinearLayoutManagerobjektu můžete připojit vlastního správce rozložení, který zobrazuje dvě CardView položky vedle sebe, implementací animačního efektu s otáčením stránky pro procházení kolekcí fotek. Později v této příručce uvidíte příklad, jak upravit rozložení prohozením v jiném správci rozložení.

Zobrazit držák

Třída držáku zobrazení je volána PhotoViewHolder. Každá PhotoViewHolder instance obsahuje odkazy na ImageView přidruženou položku řádku, TextView která je rozložena v diagramu CardView zde:

Diagram CardView obsahující ImageView a TextView

PhotoViewHolder odvozuje a RecyclerView.ViewHolder obsahuje vlastnosti pro uložení odkazů na ImageView výše TextView uvedené rozložení. PhotoViewHolder se skládá ze dvou vlastností a jednoho konstruktoru:

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

V tomto příkladu PhotoViewHolder kódu je konstruktor předán odkaz na zobrazení nadřazené položky (the CardView), který PhotoViewHolder se zabalí. Všimněte si, že nadřazené zobrazení položky vždy předáváte do základního konstruktoru. Konstruktor PhotoViewHolder volá FindViewById zobrazení nadřazené položky, aby vyhledaly všechny jeho podřízené odkazy ImageView na zobrazení a TextViewuloží výsledky v Image Caption uvedeném pořadí. Adaptér později načte odkazy na zobrazení z těchto vlastností, když aktualizuje CardViewpodřízená zobrazení s novými daty.

Další informace o RecyclerView.ViewHolder, viz RecyclerView.ViewHolder třídy reference.

Adaptér

Adaptér načte každý RecyclerView řádek s daty pro konkrétní fotografii. Pro danou fotografii na pozici řádku P například adaptér vyhledá přidružená data na pozici P ve zdroji dat a zkopíruje tato data do položky řádku na pozici P v kolekci RecyclerView . Adaptér pomocí držáku zobrazení vyhledá odkazy na ImageView danou a TextView na této pozici, takže nemusí opakovaně volat FindViewById tato zobrazení, protože uživatel prochází kolekcí fotografií a opakovaně používá zobrazení.

V RecyclerVieweru je třída adaptéru odvozena od RecyclerView.Adapter vytvoření PhotoAlbumAdapter:

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;

    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }
    ...
}

Člen mPhotoAlbum obsahuje zdroj dat (fotoalbum), který je předán do konstruktoru; konstruktor zkopíruje fotoalbum do této členské proměnné. Implementují se následující požadované RecyclerView.Adapter metody:

  • OnCreateViewHolder – Vytvoří instanci souboru rozložení položky a držitele zobrazení.

  • OnBindViewHolder – Načte data na zadanou pozici do zobrazení, jejichž odkazy jsou uloženy v daném držiteli zobrazení.

  • ItemCount – Vrátí počet položek ve zdroji dat.

Správce rozložení volá tyto metody při umístění položek v rámci RecyclerView. Implementace těchto metod je zkoumána v následujících částech.

OnCreateViewHolder

Správce rozložení volá OnCreateViewHolder , když RecyclerView potřebuje nového držitele zobrazení, aby představoval položku. OnCreateViewHolder nafoukne zobrazení položky ze souboru rozložení zobrazení a zabalí zobrazení do nové PhotoViewHolder instance. Konstruktor PhotoViewHolder vyhledá a uloží odkazy na podřízená zobrazení v rozložení, jak je popsáno výše v nástroji View Holder.

Každá položka řádku je reprezentována položkou CardView , která obsahuje ( ImageView pro fotku) a ( TextView pro titulek). Toto rozložení se nachází v souboru 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>

Toto rozložení představuje jednu položku řádku v objektu RecyclerView. Metoda OnBindViewHolder (popsaná níže) kopíruje data ze zdroje dat do ImageView a TextView z tohoto rozložení. OnCreateViewHoldernafoukne toto rozložení pro dané umístění fotky RecyclerView v nové PhotoViewHolder instanci (která vyhledá a ukládá odkazy na TextView ImageView podřízená zobrazení v přidruženém CardView rozložení):

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

Výsledná instance vhdržitele zobrazení se vrátí zpět volajícímu (správci rozložení).

OnBindViewHolder

Když je správce rozložení připravený k zobrazení určitého zobrazení v RecyclerViewoblasti viditelné obrazovky, zavolá metodu adaptéru OnBindViewHolder , která vyplní položku na určené pozici řádku obsahem ze zdroje dat. OnBindViewHolder získá informace o fotce pro zadanou pozici řádku (prostředek obrázku fotky a řetězec titulku fotky) a zkopíruje tato data do přidružených zobrazení. Zobrazení se nacházejí prostřednictvím odkazů uložených v objektu držáku zobrazení (který se předává prostřednictvím 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;
}

Předaný objekt držáku zobrazení musí být nejprve přetypován na odvozený typ držáku zobrazení (v tomto případě PhotoViewHolder) před jeho použitím. Adaptér načte prostředek obrázku do zobrazení, na které odkazuje vlastnost držitele Image zobrazení, a zkopíruje text titulku do zobrazení, na které odkazuje vlastnost držitele Caption zobrazení. Tím se vytvoří vazba přidruženého zobrazení k datům.

Všimněte si, že OnBindViewHolder je kód, který se zabývá přímo strukturou dat. V tomto případě se dozvíte, OnBindViewHolder jak mapovat RecyclerView pozici položky na přidruženou datovou položku ve zdroji dat. Mapování je v tomto případě jednoduché, protože pozici lze použít jako index pole do fotoalba; Složitější zdroje dat však mohou vyžadovat další kód pro vytvoření takového mapování.

ItemCount

Metoda ItemCount vrátí počet položek v kolekci dat. V ukázkové aplikaci prohlížeče fotek je počet fotek v fotoalbu:

public override int ItemCount
{
    get { return mPhotoAlbum.NumPhotos; }
}

Další informace o RecyclerView.Adapter, naleznete v RecyclerView.Adapter třídy reference.

Seskupování všech

Výsledná RecyclerView implementace ukázkové aplikace fotek se skládá z MainActivity kódu, který vytvoří zdroj dat, správce rozložení a adaptér. MainActivitymRecyclerView vytvoří instanci, vytvoří instanci zdroje dat a adaptér a připojí správce rozložení a adaptér:

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 vyhledá a ukládá odkazy na zobrazení do mezipaměti:

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 tři přepsání požadované 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; }
    }
}

Když se tento kód zkompiluje a spustí, vytvoří základní aplikaci pro prohlížení fotek, jak je znázorněno na následujících snímcích obrazovky:

Dva snímky obrazovky aplikace pro prohlížení fotek se svislým posouváním fotek

Pokud se stíny nevykreslují (jak vidíte na výše uvedeném snímku obrazovky), upravte Vlastnosti/AndroidManifest.xml a do elementu přidejte následující nastavení atributu <application> :

android:hardwareAccelerated="true"

Tato základní aplikace podporuje pouze procházení fotoalba. Nereaguje na události, které se dotyknou položek, ani nezpracuje změny v podkladových datech. Tato funkce je přidána v rozšíření příkladu RecyclerView.

Změna správce rozložení

RecyclerViewVzhledem k flexibilitě je snadné upravit aplikaci tak, aby používala jiného správce rozložení. V následujícím příkladu se upraví tak, aby zobrazovalo fotoalbum s rozložením mřížky, které se posunuje vodorovně místo svislého lineárního rozložení. K tomu je instance správce rozložení upravena tak, aby používala GridLayoutManager následující:

mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);

Tato změna kódu nahrazuje svislou LinearLayoutManager GridLayoutManager mřížku tvořenou dvěma řádky, které se posunou vodorovným směrem. Když aplikaci zkompilujete a spustíte znovu, uvidíte, že se fotky zobrazují v mřížce a že posouvání je vodorovné místo svislé:

Ukázkový snímek obrazovky aplikace s vodorovným posouváním fotek v mřížce

Změnou pouze jednoho řádku kódu je možné upravit aplikaci pro prohlížení fotek tak, aby používala jiné rozložení s odlišným chováním. Všimněte si, že kód adaptéru ani kód XML rozložení se musel změnit tak, aby změnil styl rozložení.

V dalším tématu rozšíření příkladu RecyclerView je tato základní ukázková aplikace rozšířena tak, aby zpracovávala události kliknutí na položky a aktualizovala RecyclerView se, když se podkladový zdroj dat změní.