Stay organized with collections Save and categorize content based on your preferences.

使用 RecyclerView 建立動態清單  Android Jetpack 的一部分

藉由 RecyclerView,您可以輕鬆有效地顯示大型資料集。由您提供資料並定義每個項目的外觀,而 RecyclerView 程式庫則會在需要時動態建立元素。

顧名思義,RecyclerView 就是回收個別元素。當向下捲動螢幕而未顯示項目時,RecyclerView 並不會刪除其檢視畫面。只不過,RecyclerView 會重複使用捲動螢幕後顯示新項目的檢視畫面。重複使用可大幅改善效能、提高應用程式的回應速度,並降低耗電量。

注意:除了類別名稱之外,RecyclerView 也是程式庫的名稱。在這個網頁中,code font 中的 RecyclerView 一律代表 RecyclerView 程式庫中的類別。

主要類別

有數種不同的類別可建立動態清單。

  • RecyclerViewViewGroup,包含對應至資料的檢視表。其本身是檢視畫面,因此您可以在版面配置中新增 RecyclerView,方法和加入其他 UI 元素相同。

  • 清單中的每個個別元素都是由「檢視容器」物件定義。建立檢視容器時,沒有任何相關聯的資料。建立檢視容器後,RecyclerView 就會將該資料繫結至其資料。您可以藉由擴充 RecyclerView.ViewHolder 來定義檢視容器。

  • RecyclerView 會呼叫這些檢視畫面,並透過轉接程式中的呼叫方法,將檢視畫面繫結到其資料。擴充 RecyclerView.Adapter 即可定義轉接程式。

  • 版面配置管理員會排列清單中的個別元素。您可以使用 RecyclerView 程式庫提供的其中一個版面配置管理員,也可以定義自己的版面配置。版面配置管理員都是以程式庫的 LayoutManager 抽象類別為基礎。

您可以在 RecyclerView 範例應用程式 (Kotlin)RecyclerView 範例應用程式 (Java) 中查看所有元件如何配合在一起。

實作 RecyclerView 的步驟

如要使用 RecyclerView,您必須執行下列幾個步驟。我們將在後續章節中詳細說明這些細節。

  • 首先,請決定清單或格線的外觀。通常您可以使用 RecyclerView 程式庫的標準版面配置管理工具之一。

  • 設計清單中的每個元素外觀和行為。根據這個設計,擴充 ViewHolder 類別。您的 ViewHolder 版本提供清單項目的所有功能。檢視容器是 View 的包裝函式,而該檢視畫面由 RecyclerView 管理。

  • 定義將資料與 ViewHolder 檢視畫面相關聯的 Adapter

您也可以使用進階自訂選項,依據自己的需求自訂 RecyclerView。

規劃版面配置

RecyclerView 中的項目是由 LayoutManager 類別排列。RecyclerView 程式庫提供三個版面配置管理工具,可用於處理最常見的版面配置情境:

  • LinearLayoutManager 會在一個維度清單中排列項目。
  • GridLayoutManager 排列了 2D 格線中的所有項目:
    • 如果網格是垂直排列的,GridLayoutManager 會嘗試讓每個資料列中的所有元素具有相同的寬度和高度,但不同的資料列高度不同。
    • 如果格線已水平排列,GridLayoutManager 會嘗試讓每個資料欄的所有元素具有相同的寬度和高度,但不同資料欄寬度不同。
  • StaggeredGridLayoutManagerGridLayoutManager 類似,但不要求一列中的項目高度 (適用於垂直網格) 或同一欄中的項目寬度相同 (適用於水平格線)。因此,資料列或資料欄中的項目可能會相互偏移。

此外,您也必須設計個別項目的版面配置。設計檢視容器時,您必須具備這個版面配置,詳情請見下一節。

實作轉接程式和檢視容器

決定版面配置後,請實作 AdapterViewHolder。這兩個類別會一起運作,以定義資料的顯示方式。ViewHolderView 的包裝函式,其中包含清單中個別項目的版面配置。Adapter 視需要建立 ViewHolder 物件,並設定這些檢視畫面的資料。將檢視畫面與資料建立關聯的程序稱為「繫結」

定義轉接程式時,您需要覆寫三種主要方法:

  • onCreateViewHolder():每當需要建立新的 ViewHolder 時,RecyclerView 都會呼叫這個方法。這個方法會建立及初始化 ViewHolder 及其相關聯的 View,但不會填入檢視畫面的內容,因為 ViewHolder 尚未繫結特定資料

  • onBindViewHolder()RecyclerView 會呼叫此方法,將 ViewHolder 與資料建立關聯。這個方法會擷取適當的資料,並使用資料填入檢視容器的版面配置。舉例來說,如果 RecyclerView 顯示名稱清單,這個方法可能會從清單中尋找適當的名稱,然後填入檢視容器的 TextView 小工具。

  • getItemCount():RecyclerView 呼叫此方法以取得資料集大小。舉例來說,可以是通訊錄應用程式中的地址總數。RecyclerView 可利用這項資訊,判斷沒有其他項目可顯示的時間點。

這是一個簡單轉接程式範例,其中包含顯示資料清單的巢狀 ViewHolder。在這種情況下,RecyclerView 會顯示簡單的文字元素清單。轉接程式會傳送字串陣列,包含 ViewHolder 元素的文字。

Kotlin


class CustomAdapter(private val dataSet: Array<String>) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder).
     */
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView

        init {
            // Define click listener for the ViewHolder's View.
            textView = view.findViewById(R.id.textView)
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view, which defines the UI of the list item
        val view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(view)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.textView.text = dataSet[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

}

Java


public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private String[] localDataSet;

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder).
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);
            // Define click listener for the ViewHolder's View

            textView = (TextView) view.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }

    /**
     * Initialize the dataset of the Adapter.
     *
     * @param dataSet String[] containing the data to populate views to be used
     * by RecyclerView.
     */
    public CustomAdapter(String[] dataSet) {
        localDataSet = dataSet;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.text_row_item, viewGroup, false);

        return new ViewHolder(view);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.getTextView().setText(localDataSet[position]);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return localDataSet.length;
    }
}

系統會按照一般方式在 XML 版面配置檔案中定義每個檢視項目的版面配置。在這個範例中,應用程式有一個 text_row_item.xml 檔案,如下所示:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/list_item_height"
    android:layout_marginLeft="@dimen/margin_medium"
    android:layout_marginRight="@dimen/margin_medium"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/element_text"/>
</FrameLayout>

後續步驟

您只需要執行簡單的 RecyclerView 實作即可。不過,這個程式庫也提供許多自訂實作方法。詳情請參閱進階 RecyclerView 自訂功能一節。

其他資源

如要進一步瞭解如何在 Android 裝置上測試,請參閱下列資源。

範例應用程式