RecyclerViewのスクロール位置の復元
ActivityやFragmentが回転や遷移などで再生成された際に、RecyclerViewのスクロール位置がうまく復元できない時があります。
ViewModelなどを使ってキャッシュしている場合などは、RecyclerViewがスクロール位置を復元する前にデータをセットしてるので、位置を復元することが可能でした。
しかし、ViewModelなどのキャッシュが使えず、RecyclerViewが復元処理をしたあとにデータをセットするしかない場合などはスクロール位置を復元するのは難しい状態です。
RecyclerView: 1.2.0-alpha02
から StateRestorationPolicy
が導入され、復元のタイミングを制御できるようになりました。
StateRestorationPolicy
StateRestorationPolicy
には3種類あります。
ALLOW
: これは通常通りすぐに復元されるものです。何も指定しなければ、これがデフォルトになります。PREVENT_WHEN_EMPTY
: Adapterのデータが0件であれば復元せず、1件以上になったときに復元されます。PREVENT
: これは復元をしません。復元を実行するには、ALLOW
かPREVENT_WHEN_EMPTY
を手動で呼ぶ必要があります。
使い方
使い方は簡単です。Adapterの stateRestorationPolicy
にセットするだけです。
adapter.stateRestorationPolicy =
RecyclerView.Adapter.StateRestorationPolicy.PREVENT
動きの確認
ちょっとコードだけだと分かりにくいと思うので、わざとスクロール位置が復元されない再現コードを使いながら見ていきます。
ALLOW
まずはデフォルトのALLOWの動きです。
最初に下までスクロールしてますが、横に回転したあとはスクロール位置が一番上に戻っています。
PREVENT_WHEN_EMPTY
次に0件のときは、復元しない設定です。
ALLOWのときと違って、横に回転したあとにスクロール位置が戻っています。
PREVENT
最後に復元しない設定です。手動で復元を実行するようにコードを以下のように少し変えます。
この場合、横回転してデータが表示されて遅れてスクロール位置が復元されています。
このように、復元のタイミングを簡単に制御できるようになりました。