Genta Hirauchi

公開日:2020/03/03
更新日:2020/08/03

【Kotlin基礎】RecyclerViewで項目を一覧表示させる方法を解説

  • Kotlinでユーザー情報などを一覧表示させたい。
  • リストがタップされた時に、何かしらの処理を実行させたい。

ユーザー情報などのデータ一覧を、スクロールして閲覧できるようにしたい場合、RecyclerViewというViewを使用する事で実装できます。

RecyclerViewは、他のViewと比べると実装しなければいけない項目が多く、プログラミングを始めたばかりの方にとっては、少し難易度が高いかもしれません。しかし、使いこなせれば、実装できるアプリの幅が格段に広がりますので、是非とも習得していただきたいViewです。

本記事では、そんなRecyclerViewの実装方法を、サンプルコードを交え、わかりやすく解説致します。

目次

RecyclerViewで項目を一覧表示させる方法

RecyclerViewは、ListViewをより柔軟に使用できるように改良したViewです。

【公式ドキュメント】 : RecyclerView | Android Developers

情報の一覧を表示するだけでしたら、ListViewでも実装することができますが、RecycerViewを使用すれば、グリッド表示や横スクロールなども簡単に実装できます。

ListViewに関しましては、以下の記事で実装方法を紹介しておりますので、そちらも合わせてご覧頂けたらと思います。

【Kotlin基礎】ListViewで項目を一覧表示させる方法を解説

アプリを実装していると、配列やリストを一覧表示させたいと思うことはありませんか?Kotlinでは、ListViewというViewを使用することで、項目の一覧表示を簡単に実装することができます。本記事では、ListViewの基本的な実装方法や、より実用的な、カスタマイズしたListViewの実装方法などを、解説致します。

ライブラリの追加

まずは、RecyclerViewを使用できるようにするために、build.gradleにライブラリを追加します。

  • build.gradle
dependencies {
   (省略)
   implementation 'androidx.recyclerview:recyclerview:1.1.0'
}

RecyclerViewの最新のバージョンは、こちらから確認いただけます。

dataクラスの実装

続いて、リスト表示する情報のdataクラスを作成します。今回は、Animalというクラスを作成します。

  • Animal.kt
data class Animal(
   val name: String,
   val age: Int,
   val imageId: Int
)

Animalクラスは、名前(name)、年齢(age)、画像(imageId)をパラメータに持つよう実装しました。

カスタムAdapterクラスの実装

続いて、カスタムAdapterクラスを作成します。

  • CustomAdapter.kt
  • list_item.xml
class CustomAdapter(private val animalList: ArrayList<Animal>): RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

   // Viewの初期化
   class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
       val image: ImageView
       val name: TextView
       val age: TextView

       init {
           image = view.findViewById(R.id.image)
           name = view.findViewById(R.id.name)
           age = view.findViewById(R.id.age)
       }
   }

   // レイアウトの設定
   override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
       val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.list_item, viewGroup, false)
       return ViewHolder(view)
   }

   // Viewの設定
   override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
       val animal = animalList[position]

       viewHolder.image.setImageResource(animal.imageId)
       viewHolder.name.text = animal.name
       viewHolder.age.text = animal.age.toString()
   }

   // 表示数を返す
   override fun getItemCount() = animalList.size
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:padding="12dp">

   <ImageView
       android:id="@+id/image"
       android:layout_width="60dp"
       android:layout_height="match_parent" />

   <LinearLayout
       android:layout_width="0dp"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:orientation="vertical"
       android:layout_marginStart="16dp">

       <TextView
           android:id="@+id/name"
           android:textColor="#000000"
           android:textSize="18sp"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_marginBottom="4dp" />

       <TextView
           android:id="@+id/age"
           android:textColor="#000000"
           android:textSize="18sp"
           android:layout_width="match_parent"
           android:layout_height="wrap_content" />
   </LinearLayout>
</LinearLayout>

CustomAdapter.kt内で、ViewHolderというクラスを実装しております。このViewHolderは、1行分のレイアウト情報を定義するクラスです。後ほど紹介するonCreateViewHolderメソッドで設定したレイアウトに対応するViewを初期化します。

onCreateViewHolderメソッドでは、レイアウトの設定を行います。xmlで実装したレイアウトファイルからViewを生成し、先ほどのViewHolderに引数として渡します。

onBindViewHolderメソッドでは、1行分のレイアウトの詳細設定をします。1行ごとにこのメソッドは呼ばれ、どの行かは、positionで取得することができます。このpositionをもとに、animalListから対応する行のデータを取得し、各Viewの詳細設定を行います。

getItemCountメソッドには、何行表示するかを返します。データの数だけ表示するため、animalList.sizeを返しております。

RecyclerViewの実装

最後にRecyclerViewを実装し、作成したCustomAdapterをAdapterに設定します。

  • MainActivity.kt
  • activity_main.xml
class MainActivity : AppCompatActivity() {

   lateinit var mAdapter: CustomAdapter
   lateinit var mAnimalList: ArrayList<Animal>

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       // データの作成
       val dog = Animal("イヌ", 3, R.drawable.dog)
       val cat = Animal("ネコ", 2, R.drawable.cat)
       val elephant = Animal("ゾウ", 10, R.drawable.elephant)
       val horse = Animal("ウマ", 4, R.drawable.horse)
       val lion = Animal("ライオン", 6, R.drawable.lion)
       mAnimalList = arrayListOf(dog, cat, elephant, horse, lion)

       // RecyclerViewの取得
       val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)

       // LayoutManagerの設定
       recyclerView.layoutManager = LinearLayoutManager(this)

       // CustomAdapterの生成と設定
       mAdapter = CustomAdapter(mAnimalList)
       recyclerView.adapter = mAdapter
   }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/container"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"/>
</LinearLayout>

MainActivity.ktでは、まずデータの作成を行っております。ここで作成したデータが一覧表示されるよう実装します。

続いて、xmlで実装したRecyclerViewの取得を行っております。

その後、取得したRecyclerViewのlayoutManagerに、LinearLayoutManagerを設定しております。LinearLayoutManagerは、データを一列に表示するためのLayoutManagerです。デフォルトでは縦一列が設定されております。

横一列で表示させたい場合は、以下のように実装します。

val layoutManager = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
recyclerView.layoutManager = layoutManager

最後に、CustomAdapterの生成を行い、RecyclerViewのAdapterとして設定しております。

イベントの追加

続いて、リストやリストの要素がタップされた時に何かしらの処理を行う方法を紹介致します。

先ほどのサンプルコードのリストのレイアウトにButtonを追加し、Buttonがタップされると、タップされた行の動物が新たに追加されるように実装したいと思います。

  • CustomAdapter.kt
  • list_item.xml
  • MainActivity.kt
// インターフェースの実装
interface AddAnimalListener {
   fun buttonTapped(animal: Animal)
}

class CustomAdapter(private val animalList: ArrayList<Animal>, private val listener: AddAnimalListener): RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

   class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
       (省略)
       val button: Button

       init {
           (省略)
           button = view.findViewById(R.id.button)
       }
   }

   (省略)

   override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
       (省略)

       // ボタンタップ時に、インターフェースのbuttonTappedメソッドを呼ぶ
       viewHolder.button.setOnClickListener {
           listener.buttonTapped(animal)
       }
   }

   (省略)
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:padding="12dp">

   (省略)

   <Button
       android:id="@+id/button"
       android:text="追加"
       android:layout_width="60dp"
       android:layout_height="wrap_content" />
</LinearLayout>
class MainActivity : AppCompatActivity(), AddAnimalListener {
   (省略)

   override fun onCreate(savedInstanceState: Bundle?) {
       (省略)

       mAdapter = CustomAdapter(mAnimalList, this)
       recyclerView.adapter = mAdapter
   }

   // 追加ボタンタップ時に呼ばれる
   override fun buttonTapped(animal: Animal) {
       // リストにタップされた動物を追加
       mAnimalList.add(animal)
       // リストの再読み込み
       mAdapter.notifyDataSetChanged()
   }
}

CustomAdapter.ktには、AddAnimalListenerというインターフェースを実装しました。このインターフェースはMainActivityでimplementしておき、インターフェースに実装されているbuttonTappedメソッドをOverrideしておきます。

list_item.xmlには、新たにButtonを実装しました。それに合わせ、CustomAdapterのViewHolderにもButtonの初期化処理を追加しました。

また、onBindViewHolderメソッド内で、Buttonがタップされたら、listenerのbuttonTappedメソッドを呼ぶように実装しております。このlistenerは、コンストラクタで渡ってきます。AddAnimalListenerをimplementしたMainActivityが渡ってくる想定です。

ここまでの実装で、Buttonがタップされると、MainActivityのbuttonTappedメソッドが呼ばれるようになります。buttonTappedメソッド内では、引数として渡ってきたAnimalを新たにリストに追加し、notifyDataSetChangedメソッドで、リストの再読み込みを行うように実装しております。

まとめ

  • RecyclerViewを使用するには、ライブラリを追加する必要がある
  • ViewHolderクラスでViewの定義を行う
  • onCreateViewHolderメソッドで、レイアウトの設定を行う
  • onBindViewHolderメソッドで、Viewの詳細設定を行う
  • getItemCountメソッドには、表示させる個数を返す
  • RecyclerViewには、LayoutManagerを設定する必要がある