RecyclerView の要素を循環させる


概要

要素が循環する RecyclerView の実装方法について説明します。

なぜ要素を循環させたいのか?

Android スマートフォンを片手で操作する際、画面横幅一杯に配置した RecyclerView で横一列に要素を並べると、右利きの場合は左端に置いてある要素をタップしにくいと感じることがあります。要素が循環するように実装できれば、左端の要素を右端までスクロールして持ってきてからタップできるので、便利ではないかと考えました。

具体的には RecyclerView の要素をどう配置したいのか?

こんな感じの RecyclerView にしたいです。RecyclerView の要素は先頭が0で最後尾が∞です。

∞ の次は 0 が出てきます。

どう実装するか?

下記の Answer の通りに実装すれば簡単でした。

まあ、考えようでして、Adapter.getItemCount にものすごく大きな値を設定して、Adapter.onBindViewHolder で下記のように Item を取り出す、というやり方です。厳密には循環しているわけではありませんが、通常の使用には特に問題はありません。

実行環境

項目
Android OS 6.0
compileSdkVersion 25
buildToolsVersion 25.0.3
Programming Language Java

実装

以下の3ステップで実装可能です。RecyclerView.Adapter を修正するだけで実装可能で、特にライブラリは必要ありません。

  1. RecyclerView.Adapter.getItemCount の戻り値を極端に大きな値にする
  2. RecyclerView.Adapter.onBindViewHolder で、position を 0-items.size() までの範囲に収める
  3. 初期位置を中央にずらす

1. RecyclerView.Adapter.getItemCount の戻り値を極端に大きな値にする

上記 Stackoverflow の例では Integer.MAX_VALUE を指定しています。極端に大きな値であれば特に何でも構いません。

@Override
public int getItemCount() {
    return Integer.MAX_VALUE;
}

2. RecyclerView.Adapter.onBindViewHolder で、position を 0-items.size() までの範囲に収める

position には極端に大きな値が入るようになるため、RecyclerView の Item の個数を最大とする値に収めます。position を Items の要素数で割った余りを用いるように修正します。

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    final Item item = items.get(position % items.size());
    //...

3. 初期位置を中央にずらす

RecyclerView の初期位置を中央までずらしておくことで、左右どちらにスクロールしても終わりが見えない感じを出す、という仕掛けです。

初期位置の設定は LayoutManager.scrollToPosition(int) で可能です。

final LinearLayoutManager layoutManager
                = new LinearLayoutManager(activityContext, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
layoutManager.scrollToPosition(Adapter.mediumPosition());

まとめ

RecyclerView.Adapter に修正を加えるだけで、要素が循環する RecyclerView を実装することができました。片手で両端の要素をタップしたい時などに役立つと思います。


リンク