Fragment(RecyclerView) in LazyRowでスクロールポジションを復元する

2022/07/19に公開

画面遷移やスクロールでLazyRowのスクロール位置が失われてしまうのが寂しかったので、
対応した記録です。

ViewModel

ViewModelにはindexとoffsetのフィールドを用意します。

var offset = 0
    private set
var index = 0
    private set
    
fun setScrollPosition(index: Int, offset: Int) {
    offset = offset
    index = index
}

Composable

ComposableではViewModelにindexとoffsetを通知する処理と、スクロールのStateを設定するだけです。

@Composable
fun Sample(
    viewModel: ViewModel
) {
    val scrollPosition = LazyListState(viewModel.index, viewModel.offset)
    
    DisposableEffect(viewModel) {
        onDispose {
            viewModel.setScrollPosition(scrollPosition.firstVisibleItemIndex, scrollPosition.firstVisibleItemScrollOffset)
        }
    }
    
    LazyRow(
        state = scrollPosition
    ) {
        ...
    }
}
  • DisposableEffectで退場するタイミングでスクロール位置をViewModelに通知
  • ViewModelが持っているindex,offsetを使ってLazyListStateを作成
  • LazyListStateをLazyRowに設定

だけです。
※全体的に記事内でコードを書いたので、コピペしても動かなかったり何か問題があったりするかもです。

Discussion