本サイトは api.flutter.dev/GridView のリファレンスブログです。
1.GridView クラス
1-1.一般的なGridView
(1)スクロール可能な2次元のウィジェット配列
GridViewは、スクロール可能な2次元のウィジェット配列です。ウィジェットが行や列に沿って並べられ、グリッド形式のレイアウトを構成します。スクロール方向は、縦または横に設定することができ、グリッド全体がスクロールして表示されます。
(2)スクロール方向
グリッドの主軸方向は、スクロールする方向(scrollDirection)です。デフォルトでは縦方向(Axis.vertical)にスクロールしますが、横方向(Axis.horizontal)にスクロールするように設定することも可能です。これにより、グリッドが縦方向または横方向に無限にスクロールできるようになります。
(3)一般的なGridViewのレイアウト方法
① GridView.count
GridView.countは、グリッドのクロス軸(スクロール方向と直交する軸)に沿って固定された数のタイルを作成します。たとえば、クロス軸に3つのタイルを並べるグリッドを作成したい場合に使用します。クロス軸とは、スクロール方向に対して垂直な軸です。縦スクロールの場合、クロス軸は横方向(X軸)です。
② GridView.extent
GridView.extentは、タイルの最大クロス軸の幅(または高さ)を指定して、レイアウトを作成します。各タイルがこの最大幅以内に収まるように配置され、柔軟なグリッドレイアウトを実現します。これにより、画面幅に応じて動的にタイルの数が変わるレイアウトが可能です。
1-2.カスタムレイアウトの作成
SliverGridDelegateをカスタマイズすると、任意の2Dレイアウトを作成できます。これには、標準的なグリッド配置に限らず、非整列な配置や重なり合う配置も含まれます。SliverGridDelegateは、子ウィジェットをどのようにグリッド内に配置するかを定義するためのクラスです。
1-3.大量のウィジェットを扱う場合
GridView.builder
多数のウィジェット(無限スクロールを含む)を効率的に表示するには、GridView.builderコンストラクタを使用します。これにより、必要に応じてウィジェットを動的に作成し、メモリの効率化を図ります。この場合、gridDelegateには次のいずれかを使用します。
SliverGridDelegateWithFixedCrossAxisCount:
クロス軸に沿って固定された数のタイルを表示します。
SliverGridDelegateWithMaxCrossAxisExtent:
クロス軸に沿ってタイルの最大幅を指定し、それに基づいてレイアウトを決定します。
1-4.カスタムSliverChildDelegateを使用する場合
GridView.custom
カスタムのSliverChildDelegateを使用するには、GridView.customを使います。
SliverChildDelegateは、子ウィジェットの生成や管理方法を制御するクラスで、カスタムのデリゲートを使って、子ウィジェットの動的な生成やキャッシュの管理など、細かい挙動を定義できます。
1-5.線形の配列(リスト)を作成する場合
子ウィジェットが1次元の線形配列(リスト)として並ぶ場合は、ListViewを使います。
GridViewが2次元のグリッドに対して、ListViewは縦や横方向に1列でウィジェットを並べるレイアウトです。
1-6.初期スクロール位置の制御
ScrollController.initialScrollOffset
スクロールビューの初期スクロールオフセット(最初に表示する位置)を制御するには、ScrollControllerのinitialScrollOffsetプロパティを使用します。これにより、GridViewが初めて表示された時に、特定の位置から表示を開始することができます。
2.CustomScrollView
GridViewは、シンプルな2Dグリッドを表示するためのウィジェットですが、より柔軟なレイアウトを実現したい場合には、CustomScrollViewとSliverを使う必要があります。具体的には、グリッドとリストを組み合わせたり、SliverAppBarを追加したりするときです。
2-1.GridViewとCustomScrollViewの関係
GridViewは、基本的にCustomScrollViewに1つのSliverGridを含んだ構造です。つまり、GridViewの内部では、SliverGridが使われて2Dのグリッドレイアウトが実現されています。
したがって、もしGridViewが十分でない場合(例: グリッドとリストを混在させたい場合や、SliverAppBarと組み合わせたい場合など)、コードを直接CustomScrollViewに移行するのは比較的簡単です。
2-2.GridViewのプロパティとCustomScrollViewのプロパティの対応関係
GridViewの次のプロパティは、CustomScrollViewの同名のプロパティに直接マッピングされます。
- scrollDirection(スクロール方向)
- reverse(逆方向スクロール)
- controller(スクロールコントローラ)
- primary
- physics(スクロールの挙動)
- shrinkWrap(ビューのサイズ制御)
これらのプロパティはCustomScrollViewでも同じように使用できるので、GridViewからCustomScrollViewに移行しても、スクロールの挙動に関しては特別な調整が必要ありません。
2-3.CustomScrollView.sliversプロパティ
CustomScrollViewのsliversプロパティには、複数のSliverをリストとして渡すことができます。GridViewから移行する場合、sliversプロパティにはSliverGridが必要です。これは、GridViewのグリッド部分に相当します。
2-4.childrenDelegateとgridDelegateの対応関係
GridViewのchildrenDelegateは、SliverGridのdelegateに対応します。
これにより、SliverGridが子ウィジェットをどのように生成し、管理するかを決定します。
GridViewのgridDelegateは、SliverGridのgridDelegateに対応します。
gridDelegateは、グリッドのレイアウト(例えば、列数やタイルのサイズ)を定義する役割を果たします。
2-5.GridViewのコンストラクタとSliverChildDelegateの対応関係
GridView.countやGridView.extentのchildren引数は、SliverChildListDelegateに対応します。
このデリゲートは、リストで提供されるウィジェットを直接表示します。
一方、GridView.builderで提供されるitemBuilderとchildCount引数は、SliverChildBuilderDelegateに対応します。このデリゲートは、スクロール位置に応じて子ウィジェットを動的に生成します。
2-6.GridView.countとGridView.extentの移行
GridView.countやGridView.extentで定義されたグリッドは、それぞれSliverGrid.countとSliverGrid.extentに簡単に移行できます。これにより、列数やタイルの最大幅を指定して、同様のグリッドを作成できます。
2-7.paddingプロパティの移行
GridViewのpaddingプロパティは、CustomScrollViewではSliverPaddingを使って表現されます。
具体的には、SliverPaddingをCustomScrollView.sliversリストに追加し、その子としてSliverGridを指定します。こうすることで、グリッド全体にパディングを適用できます。
2-8.CustomScrollViewへの移行後の拡張
CustomScrollViewに移行した後、他のSliverを追加することが可能です。
例えば、SliverList(リスト形式のレイアウト)やSliverAppBar(スクロール可能なアプリバー)をsliversリストに含めることで、より複雑なレイアウトを作成できます。
これにより、グリッドとリストを組み合わせたり、スクロール可能なアプリバーを使用した複雑なレイアウトが実現できます。
3.セッション中のスクロール位置を保持する仕組み
3-1.スクロール位置の保持
スクロールビューは、セッション中のスクロール位置を自動的に保持しようとします。この保持は、PageStorageという仕組みを使用して行われます。PageStorageは、アプリ内での一時的なデータ保存に使用され、ウィジェットが破棄されて再作成された場合でも、スクロール位置などの状態が維持されるようにします。
これにより、例えば、ユーザーが画面をスクロールして別の画面に遷移した後、再び元の画面に戻ったときに、スクロール位置が以前と同じ場所に保たれるというユーザー体験が提供されます。
3-2.ScrollController.keepScrollOffset
スクロール位置の保持機能は、ScrollControllerのkeepScrollOffsetプロパティをfalseに設定することで無効にできます。デフォルトでは、このプロパティはtrueに設定されており、スクロール位置は自動的に保持されますが、特定の状況ではこの機能をオフにしたい場合もあります。
例えば、スクロール位置を保持したくない場合や、新しいスクロール位置から再開したい場合は、このプロパティをfalseに設定します。
3-3.PageStorageKeyの利用
スクロールビューが複数存在する場合、それぞれのスクロール位置を区別するためにPageStorageKeyを使用することが推奨されています。PageStorageKeyは、PageStorage内でウィジェットの状態を保存する際の一意の識別子として機能します。
同じスクロールビューが複数の異なる場所で使われている場合(例えば、リストビューが複数ある場合)、PageStorageKeyを使ってそれぞれのスクロール位置を正しく識別し、混同を避けることができます。
例えば、2つの異なるリストビューが同じページに表示されている場合、PageStorageKeyを使ってそれぞれに異なるキーを割り当てれば、それぞれのリストビューのスクロール位置が個別に保持されます。