【Kotlin】リサイクラービューでリスト表示【Androidアプリ開発】
今回のAndroidサンプルプロジェクトでは、リサイクラービューを使って図の正方形のリストアイテムの表示を行ってみた。
この記事ではリサイクラービューの実装手順を説明していく。
リサイクラービューとは
リサイクラービューとは、リストビューよりも柔軟性の高い表現ができるビューである。リスト内にカードやカルーセルを並べたり、横方向にスクロールさせたり、リストアイテムをグリッド状に並べたりすることができる。
リサイクラービューのレイアウトマネージャーには次の3つが用意されている。
- LinearLayoutManager
- GridLayoutManager
- StaggeredGridLayoutManager
これからリサイクラービューを使う上で注意しておきたいのは、リサイクラービューはサポートライブラリーに含まれることだ。サポートライブラリとは古いOSでも使用できるように後方互換を考慮したライブラリだ。リサイクラービューはバージョン7に含まれるのでGradleでは次のように追加されることになる。
implementation 'com.android.support:recyclerview-v7:28.0.0'Adapterクラスの作成
それではリサイクラービューを作っていこう。 リストビューの時と違ってBaseAdapterではなくRecyclerViewに定義されているAdapterクラスを継承して実装する。 またリストビューと同様にViewHolderパターンを使用する。
class SampleAdapter(context: Context, private val onItemClicked: (TimeZone) -> Unit):
RecyclerView.Adapter<SampleAdapter.SampleViewHolder>() {
private val inflater = LayoutInflater.from(context)
private val timeZones = TimeZone.getAvailableIDs().map {
id -> TimeZone.getTimeZone(id)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SampleViewHolder {
val view = inflater.inflate(R.layout.list_time_zone_row, parent, false)
val viewHolder = SampleViewHolder(view)
view.setOnClickListener {
val position = viewHolder.adapterPosition
val timeZone = timeZones[position]
onItemClicked(timeZone)
}
return viewHolder
}
override fun getItemCount(): Int = timeZones.size
override fun onBindViewHolder(holder: SampleViewHolder, position: Int) {
val timeZone = timeZones[position]
holder.timeZone.text = timeZone.id
}
class SampleViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val timeZone = view.findViewById<TextView>(R.id.timeZone)
}
}
リサイクラービューで実装すべきメソッドは次の3つである。
- getItemCount():Int
- onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
- onBindViewHolder(holder: SampleViewHolder, position: Int)
それではこれらを順番に見ていこう。
getItemCount():Int
ここではリストアイテムの件数を返すことになっている。リストビューの時とは異なり、ヘッダーやフッターもカウントの対象となることに注意しよう。今回はヘッダーもフッターも表示しないのでTimeZoneで得られた配列のサイズをそのまま返すことになっている。
onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
ここでは表示するリストアイテムのViewをinflaterで生成する。ViewHolderパターンを使うので、RecyclerView.ViewHolderを継承したSampleViewHolderクラスを作りそれを返すことにした。またリストアイテムをクリックしたときのイベントハンドラの登録もここで行うようにしよう。
onBindViewHolder(holder: ViewHolder, position: Int)
ここではonCreateViewHolderで生成したViewHolderが渡されるので、表示させたい値をここで設定しよう。
MainActivityでRecyclerViewの設定
RecyclerViewのプログラムができたところで、MainActivityからRecyclerViewを呼び出す設定をしよう。class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sampleAdapter = SampleAdapter(this) { timeZone ->
Toast.makeText(this, timeZone.displayName, Toast.LENGTH_SHORT).show()
}
val gridManager = GridLayoutManager(this, 4)
val recyclerView = findViewById<RecyclerView>(R.id.timeZoneList). apply {
adapter = sampleAdapter
layoutManager = gridManager
}
}
}
今回はSampleAdapterクラスのコンストラクタの第二引数に、ラムダ式を渡す仕様となっている。ラムダ式内にリストアイテムがクリックされたときの処理を書き込もう。 GridLayoutManagerの第二引数には1行に配置したいリストアイテムの数を指定することができる。
以上のプログラムをBuild&Runすると、リサイクルビューを表示することができた。
正方形のマスを画面サイズに合わせてキレイに配置する
ところで、正方形のリストアイテムをグリッドで並べたい場合、どうすればよいだろうか?
まず、list_time_zone_row.xmlのTextViewのサイズを次のように固定にしてしまおう。
android:layout_width="80dp"
android:layout_height="80dp"
しかし画面が回転したりして横幅が大きくなってしまうと、ムダにスペースが空いてしまう。そこで画面の現在の横幅(dp)を取得して何個リストアイテムを入れられるか計算させる。onCreateメソッド内を次のように修正した。
val screenWidthDp = resources.configuration.screenWidthDp // 追記
val spanCount:Int = screenWidthDp / 88 // 追記
val gridManager = GridLayoutManager(this, spanCount) // spanCountに修正
すると次のように画面サイズに合わせてキレイに配置することができた。
以上でリサイクラービューの基本的な使い方の説明を終わる。 今回のサンプルはGitHubへ公開しておく。 AndroidExercise/TryRecyclerView · GitHub
公式ドキュメント
RecyclerView でリストを作成する - Androidデベロッパードキュメントガイド
▼ こんな記事も書いてます。