【Android × Kotlin】RecyclerView でリスト表示する
今回は、RecyclerView でリスト表示する方法を解説します。
なお、ここに掲載しているソースコードは以下の環境で動作確認しています。
- Android Studio Bumblebee | 2021.1.1 Patch 3
- JDK 11.0.11
- Android Gradle Plugin 7.1.3
- Kotlin 1.6.21
- Gradle 7.4.2
- androidx.recyclerview 1.2.1
RecyclerView でリスト表示する
RecyclerView とは、大きなデータセットを並べて表示できる ViewGroup です。並べ方を設定することができ、リストやグリッドなどで表示することができます。
今回は、以下のようなリストを表示してみます。
ライブラリのインポート
RecyclerView を使えるようにするために、アプリの build.gradle ファイルに次の依存関係を追加します。
dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1"
}
データクラスの作成
まず、RecyclerView に表示するデータクラスを作成します。今回は、リストの各項目ごとに 2 つの文字列を表示するので、データクラスにも String 型文字列を 2 つ用意します。
data class TwoLines( val primary: String = "Primary text", val secondary: String = "Secondary text", )
レイアウトファイルの作成
次に、レイアウトファイルを作成します。RecyclerView を使用する場合、RecyclerView を構成する各項目のレイアウトファイルを作成する必要があります。
<?xml version="1.0" encoding="utf-8"?> <!-- two_lines_item.xml --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp"> <ImageView android:id="@+id/iconImage" android:layout_width="60dp" android:layout_height="wrap_content" android:src="@drawable/ic_baseline_android_24" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/primaryText" android:layout_width="0dp" android:layout_height="wrap_content" android:textColor="@color/black" android:textSize="18sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/iconImage" app:layout_constraintTop_toTopOf="parent" tools:text="Primary text" /> <TextView android:id="@+id/secondaryText" android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/iconImage" app:layout_constraintTop_toBottomOf="@id/primaryText" tools:text="Secondary text" /> </androidx.constraintlayout.widget.ConstraintLayout>
なお、Activity については、RecyclerView のインスタンスを直接 AppCompatActivity#setContentView に渡すため、Activity のレイアウトファイルを作成しません。
アダプタの作成
そして、RecyclerView のアダプタを作成します。RecyclerView のアダプタは、RecyclerView とそれに表示するデータセットを紐付ける役割を持ちます。
class TwoLinesListAdapter( private val twoLinesList: List<TwoLines> ) : RecyclerView.Adapter<TwoLinesListAdapter.ViewHolder>() { inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val primaryText: TextView = view.findViewById(R.id.primaryText) val secondaryText: TextView = view.findViewById(R.id.secondaryText) } override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.two_lines_item, parent, false) return ViewHolder(view) } override fun onBindViewHolder( holder: ViewHolder, position: Int ) { holder.apply { val twoLines = twoLinesList[position] primaryText.text = twoLines.primary secondaryText.text = twoLines.secondary } } override fun getItemCount() = twoLinesList.size }
RecyclerView のアダプタには、以下を実装する必要があります。
- RecyclerView.Adapter の継承
class TwoLinesListAdapter( private val twoLinesList: List<TwoLines> ) : RecyclerView.Adapter<TwoLinesListAdapter.ViewHolder>() { ︙
- ViewHolder の定義
ViewHolder には、RecyclerView に表示する各項目の View を持たせます。RecyclerView は自身がスクロールされるたびに、既存の ViewHolder インスタンスに新しいデータを設定することで、ViewHolder インスタンスを使い回し、効率よく動作します。
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val primaryText: TextView = view.findViewById(R.id.primaryText) val secondaryText: TextView = view.findViewById(R.id.secondaryText) }
- RecyclerView.Adapter#onCreateViewHolder のオーバーライド
ここでは、さきほど作成した ViewHolder インスタンスの生成処理を実装する必要があります。
override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.two_lines_item, parent, false) return ViewHolder(view) }
- RecyclerView.Adapter#onBindViewHolder のオーバーライド
ここでは、引数に渡された ViewHolder インスタンスに新しいデータを設定する処理を実装する必要があります。
override fun onBindViewHolder( holder: ViewHolder, position: Int ) { holder.apply { val twoLines = twoLinesList[position] primaryText.text = twoLines.primary secondaryText.text = twoLines.secondary } }
- RecyclerView.Adapter#getItemCount のオーバーライド
このメソッドは、RecyclerView に表示するデータセットのサイズを返す必要があります。
override fun getItemCount() = twoLinesList.size
RecyclerView の設定
最後に、RecyclerView に対して必要な設定を行います。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) RecyclerView(this).also { it.layoutParams = ViewGroup .LayoutParams(MATCH_PARENT, MATCH_PARENT) setContentView(it) // リスト表示 val layoutManager = LinearLayoutManager(this@MainActivity) it.layoutManager = layoutManager // 罫線の追加 val dividerItemDecoration = DividerItemDecoration( this@MainActivity, layoutManager.orientation ) it.addItemDecoration(dividerItemDecoration) // データの追加 val data: List<TwoLines> = List(20) { TwoLines() } it.adapter = TwoLinesListAdapter(data) } } }
今回は、RecyclerView に対して以下の設定を行います。
- LayoutManager の設定
データセットの並べ方を設定します。今回はリスト表示なので、LinearLayoutManager を設定します。
// リスト表示 val layoutManager = LinearLayoutManager(this@MainActivity) it.layoutManager = layoutManager
- ItemDecoration の追加
RecyclerView は、デフォルトの設定では罫線を表示しません。罫線を表示させるために、DividerItemDecoration を追加します。
// 罫線の追加 val dividerItemDecoration = DividerItemDecoration( this@MainActivity, layoutManager.orientation ) it.addItemDecoration(dividerItemDecoration)
- アダプタの設定
さきほど作成したアダプタにデータセットを設定し、そのアダプタを設定します。
// データの追加 val data: List<TwoLines> = List(20) { TwoLines() } it.adapter = TwoLinesListAdapter(data)
参考
関連記事
RecyclerView に View Binding を導入する方法について、以下で解説しています。