LoginSignup
1
0

More than 1 year has passed since last update.

【Android】RecyclerViewの超基本

Posted at

はじめに

よくリスト表示で使われるRecyclerView。
Android始めたての時はなかなか基本的な使い方がわからず困った記憶があるので、改めて初心にかえって基本的な実装方法を記してみたいと思います。
間違いや気になる点がありましたらお気軽にコメント頂けますと幸いです。

完成形

こんな感じのシンプルなリストをRecyclerViewで作っていきたいと思います。
Screenshot_1653211534.png

実行環境

項目 情報
PC MacBook Pro (14-inch,2021)
CPU Apple M1 Pro 10-core
GPU Apple M1 Pro 16-core
OS macOS Monterey (12.0.1)
Android Studio Arctic Fox 2020.3.1 Patch4

前提

  • 基本的なところにフォーカスしたいので、値を外部から入れたりdata classを作るなどの処理は行いません。
  • 親FragmentにRecyclerViewを載せる構成で作成していきます。
  • 本記事ではビューの取得にビューバインディングを使用しています。ビューバインディングってなんぞやという方はこちら

RecyclerViewの概要

RecyclerViewは

  • RecyclerView自体を表示する親View
  • リスト1行分を表示するためのレイアウト&ViewHolder
  • 表示処理を管理するAdapter

で構成されています。
それぞれについてはこれからコードを追いながら見ていきます。

RecyclerViewを載せる親Fragmentの実装

まずは親FragmentにRecyclerViewを追加していきます。

MainFragment.kt
class MainFragment : Fragment(R.layout.main) {

    var binding: MainBinding? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding = MainBinding.bind(view)
    }
}
main.xml
<?xml version=“1.0” encoding=“utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android=“http://schemas.android.com/apk/res/android”
  android:layout_width=“match_parent”
  android:layout_height=“match_parent”
  xmlns:app=“http://schemas.android.com/apk/res-auto”>

  <androidx.recyclerview.widget.RecyclerView
    android:id=“@+id/main_recycler_view”
    app:layoutManager=“androidx.recyclerview.widget.LinearLayoutManager”
    android:layout_width=“match_parent”
    android:layout_height=“match_parent” />

</androidx.appcompat.widget.LinearLayoutCompat>

MainFragment.ktに関してはコンストラクタにID指定していたりビューバインディングを使用したりしていますが、細かいところなのでこの辺りのやり方はご自由にどうぞ。とりあえず現段階で表示ができれば問題ありません。

今回は全面にrecyclerViewを表示したいので、widthもheightもmatch_parentにしています。

それ以外は特別なことなしていませんが、1点重要なのがapp:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
の部分です。これがないと表示されません。
今回指定しているLinearLayoutManagerは、リスト形式で要素を配置します。TwitterのタイムラインやTODOリストみたいなイメージですね。
他には写真フォルダのように要素を配置するGridLayoutManagerや、GridLayoutの高さや幅をバラバラにできるStaggeredGridLayoutManagerが用意されています。詳細はこちら

ViewHolderの作成

ViewHolderはリスト1行分の箱のような役割を担います。
RecyclerViewはViewHolderを使い回すことで成り立っています。

main_item.xml
<!— 1行分のレイアウトを作成 —>
<TextView
  xmlns:android=“http://schemas.android.com/apk/res/android”
  android:id=“@+id/main_item_text”
  android:layout_width=“match_parent”
  android:layout_height=“100dp”
  android:text=“aaa”
  android:background=“@color/teal_200" />

まずはリスト1個分のレイアウトを作成します。
今回はごくシンプルにTextViewのみを配置しています。
ここを凝ったレイアウトにすれば、凝ったレイアウトが続々と表示されるようなリストにできます。

次に、ViewHolderの作成です。

MainViewHolder.kt
class MainViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
    val textView: TextView = itemView.findViewById(R.id.main_item_text)
}

ここの引数の入れ方は色々やり方があるようで、

MainViewHolder.kt
class MainViewHolder(val binding: MainItemBinding): RecyclerView.ViewHolder(binding.root)

とかやっているのも目にします。今回は前者で実装します。
ちなみにこの引数には後程ご紹介するAdapterで値を入れます。

Adapterの実装

いよいよrecyclerViewのAdapterを作成していきます。

MainAdapter.kt
class MainAdapter : RecyclerView.Adapter<MainViewHolder>() {

// その名の通りViewHolderを作成。MainViewHolderの引数にinflateしたレイアウトを入れている
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
    return MainViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.part_item_model, parent, false)
    )
  }

// ViewHolder内に表示するデータを指定。
  override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
    holder.binding.MainItemText.text = "${position}番目です"
  }

// 表示したいリストの数を指定
  override fun getItemCount(): Int {
    return 10
  }
}

上から順に、

  • クラス宣言部分
  • onCreateViewHolderメソッド
  • onBindViewHolderメソッド
  • getItemCountメソッド

の順番で見ていきます。

クラス宣言部分

MainAdapter.kt
class MainAdapter : RecyclerView.Adapter<MainViewHolder>() {

親クラスとしてRecyclerView.Adapterを指定します。
その次の<>内には今回使用するViewHolder(今回ならMainViewHolder)を指定しますが、<RecyclerView.ViewHolder>としておくこともできるようです。

Android StudioでRecyclerView.Adapterを継承した状態でクラス名にカーソルを合わせると下画像のようなエラーが出ると思いますが、それは必要なメソッドを実装していないためです。
スクリーンショット 2022-05-10 23.26.47.png
これは下記3つのメソッドを実装するとエラーが消えます。(画像内の「implement membersをクリックすると説明文ともにメソッドの雛形が用意されます。)

onCreateViewHolderメソッド

MainAdapter.kt
// その名の通りViewHolderを作成。
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
    return MainViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.part_item_model, parent, false)
    )
  }

ここでは先ほど作成したViewHolderをインスタンス化しています。その際に、先ほど作成したリスト1個分のレイアウト(=main_item.xml)をインフレートして引数に渡していますね。
つまりここではリスト1個分のレイアウトを作っている的な理解でいいのではないかと思います。

onBindViewHolderメソッド

リスト表示をする時、中身のデータが全て同じということはほとんどないと思います。
そのため、表示するデータをこのonBindViewHolderメソッド内で設定していきます。

MainAdapter.kt
// ViewHolder内に表示するデータを指定。
  override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
    holder.binding.MainItemText.text = "${position}番目です"
  }

先ほど作成したTextViewではtext = "aaa"となっていましたが、ここで新たにデータをセットしているので実際には○番目ですが表示されていますね。
実際はlist型でデータを渡し、[position]番目のデータを表示するといった形で使うことが多いです。

getItemCountメソッド

MainAdapter.kt
// 表示したいリストの数を指定
  override fun getItemCount(): Int {
    return 10
  }

表示したいリストの数を返します。(このくらいの記述量であれば=で書いた方がいいかもしれませんね)
return 100とすれば100番目ですが表示されるまでリストが続きますし、return 1000とすれば当然1000番目ですが表示されるまでリストが続きます(!)

Adapterを紐付ける

ここまで来たらあとはAdapterをFragmentと紐づけるだけです!
冒頭で作成したMainFragmentに下記のように付け足してください。

MainFragment.kt
class MainFragment: Fragment(R.layout.main) {
  var binding: MainBinding? = null

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

     binding = MainBinding.bind(view)
+    binding?.MainRecyclerView?.adapter = MainAdapter()
  }

冒頭で作成したmain.xml内にあるrecyclerViewにMainAdapterを指定します。意外にこの紐付け処理は忘れがちなので要注意です⚠️

さいごに

RecyclerViewは最初はなかなか理解しにくいと思うので、必要最低限なところのみ解説しました。
まだまだいろんな機能や実装方法があるので、基礎を固めたらぜひ深掘りしてみていただきたいです!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0