やりたいこと
RecyclerViewを使用して、あるデータをリスト表示するシンプルなアプリです。
環境
Android Studio: 4.1.1
Kotlin: 1.4.10
実装
データクラスを作成する
表示する情報のデータクラスを作成します。
classの前にdata
をつけることでデータクラスとして作成されます。
今回はFruitという名前にしています。
data class Fruit(
var name: String,
var imageId: Int
)
アイテムのレイアウトファイルを作成する
次に、RecyclerView内にリスト表示される1つ1つのアイテムのレイアウトファイルを作成します。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/fruit_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="18dp"
android:layout_marginEnd="18dp"
android:layout_marginStart="18dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/fruit_name"
tools:src="@drawable/apple" />
<TextView
android:id="@+id/fruit_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:textSize="24sp"
app:layout_constraintStart_toEndOf="@id/fruit_image"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/fruit_image"
app:layout_constraintBottom_toBottomOf="@id/fruit_image"
tools:text="apple" />
</androidx.constraintlayout.widget.ConstraintLayout>
レイアウトにRecyclerViewを設置する
このアプリでは、一部データバインディングを使用するので、アプリモジュールのbuild.gradle
にdataBinding
を追加します。
build.gradle(:app)
android {
...
dataBinding {
enabled = true
}
}
RecyclerViewにはリストの表示方法を設定するlayoutManager
が必須なので、忘れないように注意が必要です。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FruitFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/fruit_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Adapterを作成する
1. Adapterクラスの作成
class FruitAdapter: RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
}
class FruitAdapter
にカーソルを合わせ、option+Enter(Macの場合) -> Implement members
を選択することで、Adapterクラスに必要な3つのメソッドを自動で生成してくれます。
class FruitAdapter: RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitAdapter.ViewHolder {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: FruitAdapter.ViewHolder, position: Int) {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
}
onCreateViewHolder:新しいViewHolder
を作成する必要があるたびに呼ばれる。Viewを生成して、ViewHolder
を返す。
onBindViewHolder:position
から適切なデータを取得して、各アイテムのレイアウトと関連付ける。
getItemCount:表示するアイテム数を設定する。
2. ViewHolderを作成
まだViewHolderを作成していないため、<FruitAdapter.ViewHolder>
の部分でエラーが出るので、FruitAdapterクラス内にViewHolderを作成します。
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val fruitName: TextView = itemView.findViewById(R.id.fruit_name)
val fruitImage: ImageView = itemView.findViewById(R.id.fruit_image)
}
3. Adapterクラス内の実装
- データを保持する変数を作成
var data = ArrayList<Fruit>()
- getItemCount()
この値がRecyclerView内に表示されるアイテムの数になります。
override fun getItemCount() = data.size
- onBindViewHolder()
onBindViewHolder()
関数では、position
から取得した適切なデータを、textViewなどに設定します。
override fun onBindViewHolder(holder: FruitAdapter.ViewHolder, position: Int) {
val item = data[position]
holder.fruitName.text = item.name
holder.fruitImage.setImageResource(item.imageId)
}
- onCreateViewHolder()
layoutInflaterでViewを作成して、ViewHolderを返します。
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitAdapter.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view)
}
コード
最終的にこのようになれば、Adapterクラスの完成です。
class FruitAdapter: RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
var data = ArrayList<Fruit>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitAdapter.ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.list_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: FruitAdapter.ViewHolder, position: Int) {
val item = data[position]
holder.fruitName.text = item.name
holder.fruitImage.setImageResource(item.imageId)
}
override fun getItemCount() = data.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val fruitName: TextView = itemView.findViewById(R.id.fruit_name)
val fruitImage: ImageView = itemView.findViewById(R.id.fruit_image)
}
}
RecyclerViewにAdapterを設定する
Adapterの設定は全てonCreateView()
メソッド内で行います。
(アクティビティの場合は、onCreate()
メソッド)
1. Adapterを初期化する
val adapter = FruitAdapter()
2. データを格納する
今回はサンプルなので、あらかじめ用意したデータを表示させるようにしています。
基本的にはデータベース等から取得した動的なデータを使ったりすると思います。
val adapter = FruitAdapter()
val fruitData = arrayListOf(
Fruit("Apple", R.drawable.apple),
Fruit("Banana", R.drawable.banana),
Fruit("Cherry", R.drawable.cherry),
Fruit("Grape", R.drawable.grape),
Fruit("Orange", R.drawable.orange),
Fruit("Peach", R.drawable.peach),
Fruit("Pineapple", R.drawable.pineapple),
Fruit("Strawberry", R.drawable.strawberry)
)
adapter.data = fruitData
3. RecyclerViewにアダプターをセットする
binding.itemList.adapter = adapter
コード
class FruitFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentFruitBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_fruit, container, false)
val adapter = FruitAdapter()
val fruitData = arrayListOf(
Fruit("Apple", R.drawable.apple),
Fruit("Banana", R.drawable.banana),
Fruit("Cherry", R.drawable.cherry),
Fruit("Grape", R.drawable.grape),
Fruit("Orange", R.drawable.orange),
Fruit("Peach", R.drawable.peach),
Fruit("Pineapple", R.drawable.pineapple),
Fruit("Strawberry", R.drawable.strawberry)
)
adapter.data = fruitData
binding.itemList.adapter = adapter
return binding.root
}
}
今回はRecyclerViewの使い方がメインのため、データバインディングの説明は省いています。