こんにちは、モバイルクライアントチームの明渡です。
直近数ヶ月メインの開発がもっぱらFlutterで、久々にiOSで1画面作ってみたら忘却の彼方にあったiOS独特の細かいクセが要因で少し手こずりました。 新しいことに取り組むのは大事だし楽しいですが、身につけたことが錆びないようにするのも大事ですね。
今回は、今年4月にリリース済みのとあるFlutter Web製アプリケーションにて、Studyplusアプリと同様の本棚表示を実装したことについてお話しします。
リリース済みのとあるFlutter Web製アプリケーション
一部のユーザーを対象として提供している、学習記録管理Webアプリケーションです。
主にStudyplusのモバイル版を利用するのが難しいが、しかし学習管理を行いたいユーザー向けに提供しています。 現時点では、モバイル版の一部機能を利用できるようにしています。
FlutterのSliversとは
端的に表現すると、複数のリスト系Widgetを1個のスクロール領域へ地続きに表示するための仕組みです。 公式ドキュメントで動画などを確認するとイメージがつきやすいです。
Studyplusアプリの本棚画面(iOS)
基本的にいたって普通の、UICollectionViewを用いた構成です。
図のうち、背景を塗りつぶした項目はユーザーから視認できるUI要素です。 1個目のセクションで条件により入れ子でUICollectionViewを持ちますが、2個目以降は本棚を構成するカテゴリー毎にSectionを分けて表示しています。
Flutterでもこちらを参考に、似たような構成で画面を作ろうとしていました。
Flutter Web製アプリケーションでの本棚画面
Flutterで同じ機能を提供するため、最終的には以下の通り実装しました。
iOSにてSectionHeaderに該当するパーツをSliverStickyHeader、CollectionViewCellを含むSectionはSliverGridで対応しました。
CustomScrollView上に、SliverStickyHeaderとSliverGridをセットで羅列していくような形です。
Sliversで実現できなかったこと
上記に落ち着くまで以下の構成を描いて実装を試み、エラーが発生し続けて頭を抱えていました。
本棚画面のうち、有料コンテンツを含む要素とそれ以外でSliverListを分離しつつ、ListItemにてiOSでいうところのSection単位を実現したかったのです。
取り扱うデータの属性が異なる一覧は実装上も違う階層で取り扱えると見やすくて嬉しかったのですが、ダメでした。
CustomScrollViewは、子のSliverクラスが最終的にどの程度の高さとなるか確認してから描画する性質があります。 しかしながら、子が更に孫にあたるSliverクラスを含んでいても、孫以降の階層の高さまでは確認しないようなのです。
なお、孫にあたるSliverクラスをCustomScrollViewでラップしても結果は同じエラーでした。
FlutterのSliversについてのドキュメントや公式のサンプルコードでもSliver入れ子構造にしている例は見当たらなかったのですが、できないとはどこにも書いてないのでできる前提で実装を試み続けてハマりました。
さいごに
以上、FlutterのSliversに苦戦しつつ実装した話でした。
ネイティブアプリでの経験を基礎として実装するにしても、基礎を当てにしすぎると痛い目を見るんだなと印象に残っていたので記事に起こしてみました。
Flutterへ既にすっかり馴染みのある方には易しい内容だったかもしれないですが、今後FlutterのSliversに触れる方にとって何か参考にできることがあれば嬉しいです。