のんびり精進

調べた情報などをおすそ分けできれば。

【Flutter】SliverAppBarとTabBarを組み合わせたときに各タブのスクロール位置を保持したい

Flutterでは伸び縮みするApp Barを使うのも簡単に実装できます。

でも、タブを表示して中にListViewなどを表示すると、各タブ内のスクロール位置が連動してしまいました…。 例えば、1つ目のタブのリストでスクロールして2つ目のタブに切り替えると、そのタブでも同じ位置までスクロールした状態になっています。

やり方が悪い可能性も考えて公式ドキュメントでコード例を探してみたところ、NestedScrollView のところにありました。

PageStorageKeys are used to remember the scroll position of each tab's list.

「各タブのリストのスクロール位置を保つには PageStorageKeys を使います」と書かれています。 実現したいのはまさにこれです。

上のリンク先に書かれている例は DefaultTabController 以下のみの断片的なコードなので、動くコードにして試しました。

DartPad

f:id:kabochapo:20190121000700g:plain

できた!

と一瞬思ったのですが、ぬか喜びでした。

  1. Tab1 で Item 3 までスクロール
  2. Tab2 で Item 5 までスクロール
  3. 各タブで Item 3、Item 5、Item 0 の位置になっている(ここまでOK)
  4. Tab3 で Item 8~9 あたりまでスクロール
  5. Tab2 が Item 14 までスクロールしてしまっている
  6. Tab2 で Item 12 まで戻す
  7. Tab1 も Tab3 も先頭(Item 0)まで戻ってしまっている

公式ドキュメントのサンプルでも起こるならFlutter自体のバグですね。

なお、この問題は既に報告されていました。

github.com

Issue の報告者自身が解決策を書いていますが、Pull Request ではなく新たなパッケージのような形にされています。 また、それを使ってみましたが解決しませんでした。 使い方の理解が足りないのかそのパッケージの問題なのかわかりません。 Flutter 本体が修正されるのはまだ先になりそうです。

改善されたかも(2019/6/27 追記)

数ヶ月前

 同じコードを実行すると、上記のおかしな挙動の頻度が減っていて、少し改善されているようでした。

本日

 久しぶりに再び実行してみたところ、しばらく操作しても再現しませんでした。
 見落としかもしれませんが、GitHub の Issues や Releases にも関連情報が見当たりません。
 完全に直ったとは判断できませんが、そろそろ使っても良さそうです。