GridView
GridView
GridViewは写真などのボックス状のレイアウトを配置しスクロールするのに便利なウィジェットです。
それでは細かいところを一つずつみていきましょう。
GridViewを構築するためには4つの方法があります。
- 「GridView.count」は最も一般的に使用されるグリッドレイアウトとなり、横に並べる数を固定数で指定してグリッドを表示します。
- 「GridView.extent」は横に並べる幅を指定値分最大限確保してグリッドを並べる表示に方法になります。
- 「GridView.builder」で作成すると、実際に表示されている子要素のみビルダーが呼び出されるため随時読み込みなど、多数(または無限)のリストを表示する場合に利用する作成方法です。
- 「GridView.custom」で作成すると、「SliverGridDelegate」を追加してカスタマイズでき、整列されていないまたは重ねた配置を実現できます。
今回は、1~3について説明していきます。
GridView.count
一般的なGridViewの表示方法です。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var list = [
_photoItem("pic0"),
_photoItem("pic1"),
_photoItem("pic2"),
_photoItem("pic3"),
_photoItem("pic4"),
_photoItem("pic5"),
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GridView'),
),
body: GridView.count(
crossAxisCount: 2,
children: list
)
)
);
}
Widget _photoItem(String image) {
var assetsImage = "assets/img/" + image + ".png";
return Container(
child: Image.asset(assetsImage, fit: BoxFit.cover,),
);
}
}
このようにcrossAxisCount
で横に並べる件数を指定することでグリッドが並びます。
GridView.extent
GridView.extent
はmaxCrossAxisExtent
で指定した幅を最大値として、グリッドを並べる表示方法です。
例えば、500pxの横幅のある「GridView」に対して、maxCrossAxisExtent
を150と指定した場合、幅125pxのグリッドが4列並んだ表示となります。
body: GridView.extent(
maxCrossAxisExtent: 150,
padding: const EdgeInsets.all(4),
mainAxisSpacing: 4,
crossAxisSpacing: 4,
children: list
)
padding
で「GridView」の外周のPaddingを設定し、mainAxisSpacing
、crossAxisSpacing
によりグリッド間にスペースを作っています。
今回のGridViewは幅400pxのため、グリッドの間の数値を引いて128pxのグリッドが3列になっている状態です。
GridView.builder
GridView.builder
は「ListView」の時同様、表示する要素が事前にわからない場合に利用する書き方です。itemBuilder
は画面表示時に実行されるため、無限にグリッドを作成することが可能です。
ギャラリー、検索結果の表示などに利用すると良いかと思います。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var grid = ["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GridView'),
),
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
)
);
}
Widget _photoItem(String image) {
var assetsImage = "assets/img/" + image + ".png";
return Container(
child: Image.asset(assetsImage, fit: BoxFit.cover,),
);
}
}
上記の例ではitemBuilder
で画像を表示するウィジェットを作成しています。
また、gridの件数が表示件数を上回る場合に追加で画像を生成しています。
このようにすることで無限にグリッドが生成される状態になりました。
SliverGridDelegateWithFixedCrossAxisCount
builder
で利用している、SliverGridDelegateWithFixedCrossAxisCount
はGridView.count
と同じです。crossAxisCount
で横に並べる数を指定して、グリッドを作成します。
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
SliverGridDelegateWithMaxCrossAxisExtent
builder
では、SliverGridDelegateWithMaxCrossAxisExtent
も利用でき、GridView.extent
と同じ制御が可能です。maxCrossAxisExtent
で横に並べるグリッドの最大幅を指定して、グリッドを作成します。
body: GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
ScrollDirection
「GridView」クラスであればどれでも利用できるのですが、scrollDirection
はグリッドを並べる方向を変更するために使います。
デフォルトではAxis.vertical
です。
body: GridView.builder(
scrollDirection: Axis.horizontal,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
このようにスクロールする方向が変わったのがわかると思います。
AxisSpacing
グリッド同士の間にスペースを作成したいときに指定するのが、mainAxisSpacing
とcrossAxisSpacing
になります。
RowやColumnでも同じ考え方が出てきましたが、以下のようなイメージで利用します。
このプロパティは、「GridView」クラスであれば上記で説明したどれでも利用できます。
このように並ぶ方向に対して、mainAxisSpacing
とcrossAxisSpacing
が決まることに注意してください。
特に、先に説明したscrollDirection
と併用する場合はスペース位置が変わりますのでお気をつけください。
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 4,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
このように上下に対してスペースができます。
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 4,
),
itemBuilder: (BuildContext context, int index) {
if (index >= grid.length) {
grid.addAll(["pic0", "pic1", "pic2", "pic3", "pic4", "pic5",]);
}
return _photoItem(grid[index]);
}
)
このように左右に対してスペースができます。
ChildAspectRatio
今まで紹介したやり方だとGridのタテヨコ比は常に同じ割合となります。
そのため縦の長さを伸ばしたい場合は、childAspectRatio
で比率を変えてあげます。
このプロパティは、「GridView」クラスであれば上記で説明したどれでも利用できます。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var list = [
_photoItem("pic0"),
_photoItem("pic1"),
_photoItem("pic2"),
_photoItem("pic3"),
_photoItem("pic4"),
_photoItem("pic5"),
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('GridView'),
),
body: GridView.count(
crossAxisCount: 2,
childAspectRatio: 0.7,
children: list
)
)
);
}
Widget _photoItem(String image) {
var assetsImage = "assets/img/" + image + ".png";
return Container(
child: Image.asset(assetsImage, fit: BoxFit.cover,),
);
}
}