😽

【Android】(Kotlin)recyclerViewの特定の要素が表示されたら処理を行う

2023/04/12に公開

基本方針

  1. アダプターに「特定の要素の位置」を保存する
  2. onScrolled()をオーバーライドし、スクロールの度に判断を行う
  3. 「最後に表示されている要素の位置」が「特定の要素の位置」に到達したら処理を実行する

コードと解説

まずは、特定の要素の位置をアダプター内部で保持します。

// アダプターに渡すデータのリストをlistとしています。
val list = {...}
var position: Int
  get() {
    var value = -1
    list.forEachIndexed { index, item ->
      // ここで特定の要素の判別を行う(以下はtitleで判別する場合の例)
      if (item.title == "hoge") value = index
    }
    return value
  }

次に、RecyclerViewのOnScrollListener()内、onScrolled()をオーバーライドします。

RecyclerViewの表示処理を行うFragment内部に

private val onScrollListener = object : RecyclerView.OnScrollListener() {
  override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
    super.onScrolled(recyclerView, dx, dy)
    // RecyclerViewの要素をrecyclerItemとして定義してください。
    val recyclerItem = binding.hogeRecyclerItem
    val linearLayoutManager = recyclerItem.layoutManager as LinearLayoutManager
    val lastVisibleItem = linearLayoutManager.findLastCompletelyVisibleItemPosition()
    // ここに条件判定を入れる(adapterは上で定義したものを参照できるようにしておいてください。)
    if (lastVisibleItem >= adapter.position) {
      // ここに実行したい処理を入れる
    }
  }
}

注意点

条件分岐の中で

if (lastVisibleItem >= adapter.position)

という記述がありますが、ここは==にすると高速にスクロールした時に処理が呼ばれない可能性があります。
そのため、「表示され終わった要素の位置」が「トリガーにしたい要素の位置」以上となるように記述しています。

スクロール速度を制限する方法もありますが、ユーザーインターフェイスに悪影響を及ぼす可能性があるため、避けるべきです。

Discussion