この記事ではRecyclerViewを上下にスクロールしたときに要素が勝手に変わってしまう原因とその解決方法について解説します。
サンプルコード付きで説明しているのでぜひ参考にしてみてください。
RecyclerViewの要素が勝手に変わる原因
RecyclerViewをスクロールしたときに要素が勝手に変わってしまう原因は、RecyclerViewの要素が再利用されているからです。
RecyclerViewは要素を再利用することでパフォーマンスを改善するという特徴を持っています。
以下の画像はRecyclerViewで5の倍数の要素には取り消し線を入れる実装をした時の挙動です。

この画像のように要素を再利用するというRecyclerViewの特性によって上下にスクロールしたときに正しい挙動にならないということが起こります。
解決方法
RecyclerViewを正しい挙動にするための解決方法を3つ紹介します。
解決方法①
1つ目の解決方法は要素がifの内容と一致しなかった場合の挙動をelseで指定することです。
以下は5の倍数の要素に取り消し線をつける挙動のサンプルコードです。
if(num % 5 == 0){
//numが5の倍数のときnumTextに取り消し線を表示
holder.numText.paintFlags = holder.numText.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
}else{
//numが5の倍数以外のときnumTextは取り消し線を表示しない
holder.numText.paintFlags = 0
holder.numText.paint.isAntiAlias = true
}
ポイントはifの内容と一致しなかったときの挙動をelseで指定しているところです。
ifの内容と一致しなかったときの表示が指定されていないと、要素がそのまま再利用されてしまうため正しい挙動になりません。elseも記述しておくことで正しい挙動になります。
解決方法②
2つ目の解決方法は以下のコードをAdapterに追加する方法です。
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemViewType(position: Int): Int {
return position
}
そして、以下のようにadapterにsetHasStableIds(true)を設定します。
adapter.setHasStableIds(true)
これらのコードを追加することでRecyclerViewが要素のIDを参照するようになるため、スクロールしても正しく要素が表示されるようになります。
解決方法③
3つ目の解決方法はRecyclerViewを再利用しないようにする方法です。
AdapterのonBindViewHolder内に以下のコードを追加します。
holder.setIsRecyclable(false)
このコードを追加することでRecyclerViewが再利用されなくなるので、RecyclerViewをスクロールしても要素が正しく表示されるようになります。
まとめ
今回はRecyclerViewの要素が勝手に変わる原因と解決方法について解説しました。いかがだったでしょうか。
3つの解決方法を紹介しましたが、どの方法も簡単に実装できるので是非参考にしてみてください。


コメント