共用方式為


基本回收工具檢視範例

若要瞭解一般應用程式中的運作方式 RecyclerView ,本主題會探索用來顯示大量相片集合的簡單程式代碼範例 RecyclerView

使用 CardView 顯示相片之 RecyclerView 應用程式的兩個螢幕快照

RecyclerViewer 會使用 CardView 在版面配置中實作 RecyclerView 每個相片專案。 RecyclerView由於效能優點,此範例應用程式能夠順暢且不會明顯延遲地快速捲動大型相片集合。

數據源範例

在此範例應用程式中,「相簿」數據源(由 PhotoAlbum 類別表示)會 RecyclerView 提供項目內容。 PhotoAlbum 是具有標題的相片集合;當您具現化它時,您會收到 32 張照片的現成集合:

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

中的每個PhotoAlbum相片實例都會公開屬性,讓您讀取其影像資源識別碼,PhotoID以及其標題字串 。 Caption 相片的集合會組織,讓每個相片都可以由索引器存取。 例如,下列幾行程式代碼會存取集合中第十張照片的影像資源標識碼和標題:

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

PhotoAlbum 也提供 RandomSwap 方法,您可以呼叫 來將集合中的第一張相片交換為集合中其他位置的隨機選擇相片:

mPhotoAlbum.RandomSwap ();

由於的 PhotoAlbum 實作詳細數據與了解 RecyclerView無關, PhotoAlbum 因此此處不會顯示原始程式碼。

版面配置和初始化

設定檔案 Main.axml 是由 中的LinearLayoutRecyclerView一所組成:

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

請注意,您必須使用完整名稱 android.support.v7.widget.RecyclerView ,因為 RecyclerView 已封裝在支持連結庫中。 初始化 OnCreate 此配置的方法 MainActivity 、具現化配接器,並準備基礎數據源:

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

此程式碼會執行下列操作:

  1. 具現化 PhotoAlbum 數據源。

  2. 將相簿數據源傳遞至配接器的建構函式( PhotoAlbumAdapter 本指南稍後定義)。 請注意,最佳做法是將數據源當做參數傳遞至配接器的建構函式。

  3. RecyclerView從版面設定取得 。

  4. 呼叫 方法,將配接器插入 實例, RecyclerView RecyclerView SetAdapter 如上所示。

版面配置管理員

中的每個RecyclerViewCardView專案都是由 包含相片影像和相片標題的 組成(下方檢視持有人區段涵蓋詳細數據)。 預先定義的 LinearLayoutManager 是用來以垂直捲動排列方式設定每個 CardView 配置:

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

此程式代碼位於主要活動的方法中 OnCreate 。 設定管理員的建構函式需要 內容,因此 MainActivity 會使用 this 如上所示傳遞 。

您可以插入自訂版面配置管理員,以並排顯示兩CardView個項目,實作翻頁動畫效果來周遊相片集合,而不是使用預先LinearLayoutManager定義的 。 稍後在本指南中,您將會看到如何在不同版面配置管理員中交換來修改版面配置的範例。

檢視持有人

檢視持有者類別稱為 PhotoViewHolder。 每個PhotoViewHolder實例都會保存關聯數據列項目的 參考ImageViewTextView,其配置CardView如下圖所示:

包含 ImageView 和 TextView 的 CardView 圖表

PhotoViewHolder衍生自 RecyclerView.ViewHolder ,並包含屬性,以儲存上述版面配置中顯示的 和 TextView 參考ImageViewPhotoViewHolder 由兩個屬性和一個建構函式所組成:

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

在這裡程式代碼範例中,建PhotoViewHolder構函式會傳遞包裝之父項目檢視的參考。PhotoViewHolder CardView 請注意,您一律會將父項目檢視轉送至基底建構函式。 建PhotoViewHolder構函式會呼叫FindViewById父項目檢視,以找出其每個子檢視參考,ImageView並將TextView結果分別儲存在 和 Caption 屬性中Image。 配接器稍後會從這些屬性擷取檢視參考,以新的數據更新這個 CardView子檢視。

如需 的詳細資訊 RecyclerView.ViewHolder,請參閱 RecyclerView.ViewHolder 類別參考

配接器

配接器會載入每個 RecyclerView 數據列,其中包含特定相片的數據。 例如,對於位於數據列位置 P 的指定相片,配接器會在數據源內的位置 P 找到相關聯的數據,並將此數據複製到集合中RecyclerView位於 P 位置的數據列專案。 配接器會使用檢視持有者來查閱 和 TextView 的參考ImageView,因此當使用者捲動相片集合並重複使用檢視時,不需要重複呼叫FindViewById這些檢視。

RecyclerViewer 中,配接器類別衍生自 RecyclerView.Adapter 以建立 PhotoAlbumAdapter

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

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

成員 mPhotoAlbum 包含傳入建構函式的數據源(相簿),建構函式會將相簿複製到這個成員變數。 已實作下列必要 RecyclerView.Adapter 方法:

  • OnCreateViewHolder – 具現化專案配置檔案和檢視持有者。

  • OnBindViewHolder – 將位於指定位置的數據載入至參考儲存在指定檢視持有者中的檢視中。

  • ItemCount – 傳回數據源中的項目數。

配置管理員會在將專案放置在 內 RecyclerView時呼叫這些方法。 下列各節會檢查這些方法的實作。

OnCreateViewHolder

當 需要新的檢視持有者來代表專案時,RecyclerView配置管理員會呼叫 OnCreateViewHolderOnCreateViewHolder 從檢視的配置檔案擴充項目檢視,並將檢視包裝在新實例中 PhotoViewHolder 。 建PhotoViewHolder構函式會尋找並儲存配置中子檢視的參考,如檢視持有人先前所述。

每個數據列專案都以 CardView ImageView 包含 (針對相片) 和 TextView (標題) 的 來表示。 此設定位於 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>

此配置代表 中的 RecyclerView單一數據列專案。 方法 OnBindViewHolder (如下所述)會將資料來源 ImageView 中的資料複製到此版面設定的 與 TextViewOnCreateViewHolder在 中RecyclerView為指定相片位置擴充此版面配置,並具現化新的 PhotoViewHolder 實例(這會在相關聯的CardView版面配置中尋找和快取與TextView子檢視的參考ImageView):

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

產生的檢視持有者實例 vh會傳回給呼叫端(配置管理員)。

OnBindViewHolder

當配置管理員準備好在可見的畫面區域中顯示特定檢視 RecyclerView時,它會呼叫配接器 OnBindViewHolder 的方法,以數據源中的內容填滿指定數據列位置的專案。 OnBindViewHolder 會取得指定數據列位置的相片資訊(相片的影像資源和相片標題的字串),並將此數據複製到相關聯的檢視。 檢視是透過儲存在檢視持有者物件中的參考來找到(透過 參數傳入 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;
}

傳入的檢視持有者對象必須先轉換成衍生檢視持有者類型(在此案例中為 PhotoViewHolder),才能使用。 配接器會將影像資源載入檢視持有人的 Image 屬性所參考的檢視中,並將標題文字複製到檢視持有者屬性所參考的 Caption 檢視中。 這會 系結 相關聯的檢視與其數據。

請注意, OnBindViewHolder 是直接處理數據結構的程序代碼。 在此情況下, OnBindViewHolder 瞭解如何將 RecyclerView 專案位置對應至數據源中的相關聯數據項。 在此情況下,對應很簡單,因為位置可以當做相簿的陣列索引使用;不過,更複雜的數據源可能需要額外的程式代碼才能建立這類對應。

ItemCount

方法 ItemCount 會傳回數據收集中的項目數。 在範例相片檢視器應用程式中,專案計數是相簿中的相片數目:

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

如需 的詳細資訊 RecyclerView.Adapter,請參閱 RecyclerView.Adapter 類別參考

把它全部放在一起

範例相片應用程式所產生的 RecyclerView 實作是由 MainActivity 建立數據源、版面配置管理員和配接器的程式代碼所組成。 MainActivity 建立 mRecyclerView 實例、具現化數據源和配接器,並插入配置管理員和配接器:

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 會尋找並快取檢視參考:

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 會實作三個必要方法覆寫:

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

編譯並執行此程式代碼時,它會建立基本相片檢視應用程式,如下列螢幕快照所示:

具有垂直捲動相片卡片之相片檢視應用程式的兩個螢幕快照

如果未繪製陰影(如上述螢幕快照所示),請編輯 Properties/AndroidManifest.xml ,並將下列屬性設定新增至 <application> 元素:

android:hardwareAccelerated="true"

此基本應用程式僅支援瀏覽相簿。 它不會回應項目觸控事件,也不會處理基礎數據中的變更。 這項功能會在擴充 RecyclerView 範例新增。

變更 LayoutManager

RecyclerView因為彈性,所以很容易修改應用程式以使用不同的版面配置管理員。 在下列範例中,它會修改成使用水平捲動而非垂直線性版面配置來顯示相簿。 若要這樣做,版面配置管理員具現化會修改為使用 , GridLayoutManager 如下所示:

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

此程式代碼變更會將 垂直LinearLayoutManagerGridLayoutManager取代為 ,其呈現由兩個數據列組成的網格線,而數據列會以水準方向卷動。 當您再次編譯並執行應用程式時,您會看到相片會顯示在網格線中,而且捲動是水準而非垂直的:

在網格線中水平卷動相片的應用程式範例螢幕快照

只要變更一行程序代碼,就可以修改相片檢視應用程式,以使用不同的配置與不同的行為。 請注意,不需要修改配接器程式代碼或配置 XML 來變更版面配置樣式。

在下一個主題中, 擴充 RecyclerView 範例,此基本範例應用程式會擴充以處理項目點擊事件,並在基礎數據源變更時更新 RecyclerView