RecyclerView で動的リストを作成する Android Jetpack の一部。
RecyclerView を使用すると、大規模なデータセットを簡単かつ効率的に表示できます。データを指定し、各アイテムの表示方法を定義すると、必要に応じて、RecyclerView ライブラリが動的に要素を作成します。
RecyclerView は、その名のとおり、これらの個々の要素をリサイクルします。アイテムが画面外にスクロールされても、RecyclerView はビューを破棄せず、代わりに、RecyclerView は、画面上でスクロールした新しいアイテムのビューを再利用します。RecyclerView を使用すると、アプリのパフォーマンスと応答性が向上し、消費電力が削減されます。
主なクラス
複数のクラスが連携して動的リストをビルドします。
RecyclerView
は、データに対応するビューを含むViewGroup
です。これはビュー自体であるため、他の UI 要素と同じようにRecyclerView
をレイアウトに追加できます。リスト内の各要素はビューホルダー オブジェクトによって定義されます。ビューホルダーは、作成されるときにデータが関連付けられることはありません。ビューホルダーは、作成された後で
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 ライブラリには 3 つのレイアウト マネージャーがあり、レイアウトの標準的な状況を処理します。
LinearLayoutManager
は 1 次元のリスト内にアイテムを配置します。GridLayoutManager
は、次の 2 次元グリッド内にアイテムを配置します。- グリッドが垂直方向に配置されている場合、
GridLayoutManager
は各行のすべての要素が同じ幅と高さになるようにしますが、行ごとに異なる高さを指定することもできます。 - グリッドが水平方向に配置されている場合、
GridLayoutManager
は各列のすべての要素の幅と高さが同じになるようにしますが、列ごとに異なる幅を指定することもできます。
- グリッドが垂直方向に配置されている場合、
StaggeredGridLayoutManager
はGridLayoutManager
と似ていますが、行のアイテムの高さが同じである必要もなく(垂直グリッドの場合)、同じ列のアイテムの幅が同じである必要もありません(水平グリッドの場合)。結果として、行または列内のアイテムが互いにオフセットされることになります。
また、個々のアイテムのレイアウトも設計する必要があります。このレイアウトは、ビューホルダーを設計する際に必要になります。次のセクションで説明します。
アダプタとビューホルダーを実装する
レイアウトが決まったら、Adapter
と ViewHolder
を実装する必要があります。これら 2 つのクラスが連携して、データの表示方法を定義します。ViewHolder
は、リスト内の各アイテムのレイアウトを含む View
のラッパーです。Adapter
は、必要に応じて ViewHolder
オブジェクトを作成するとともに、これらのビューのデータを設定します。ビューをこれらのデータに関連付けるプロセスは、バインディングと呼ばれます。
アダプターを定義する際は、次の 3 つの主要なメソッドをオーバーライドする必要があります。
onCreateViewHolder()
:RecyclerView
は、新しいViewHolder
を作成する必要があるたびにこのメソッドを呼び出します。このメソッドは、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
の使用方法を示しています。
Kotlin
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val dataset = arrayOf("January", "February", "March") val customAdapter = CustomAdapter(dataset) val recyclerView: RecyclerView = findViewById(R.id.recycler_view) recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
このライブラリには、実装をカスタマイズするためのさまざまな方法が用意されています。詳しくは、RecyclerView の高度なカスタマイズをご覧ください。
参考情報
Android でのテストの詳細については、次のリソースをご覧ください。