やりたいこと
GridViewに4つのバナー画像を画面幅いっぱいに2行2列で表示したい。
下記画像のような想定です。
プレースホルダーのバナー画像は下記のサイトを使って取得しています。 Placeholder.com: Placeholder.com – The Free Image Placeholder Service Favoured By Designers
問題
軽く実装してみたところバナーの上下に想定外の余白ができてしまいました。
Imageウィジェットの高さの計算がうまくいってないようです。
実装
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'サンプルApp', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'サンプル'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const imageUrls = [ 'https://via.placeholder.com/350x80/0000FF?Text=Banner01', 'https://via.placeholder.com/350x80/FF0000?Text=Banner02', 'https://via.placeholder.com/350x80/FFFF00?Text=Banner03', 'https://via.placeholder.com/350x80/000000?Text=Banner04', ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Container( child: Container( child: GridView.count( crossAxisCount: 2, children: [for (final imageUrl in imageUrls) makeBanner(imageUrl)], )), )); } Widget makeBanner(String imageUrl) { return Image.network(imageUrl); } }
対応
GridViewのchildAspectRatioはデフォルトで「1.0」が設定されていました。
GridView.count({ Key? key, Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController? controller, bool? primary, ScrollPhysics? physics, bool shrinkWrap = false, EdgeInsetsGeometry? padding, required int crossAxisCount, double mainAxisSpacing = 0.0, double crossAxisSpacing = 0.0, double childAspectRatio = 1.0, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double? cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual, String? restorationId, Clip clipBehavior = Clip.hardEdge, })
バナーの幅と高さが同じになるようにウィジェットのサイズが計算されているようです。 対応方法としてはGridViewのchildAspectRatioにバナー画像のアスペクト比を設定したところ、想定していた通りの表示になりました。
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'サンプルApp', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'サンプル'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const imageUrls = [ 'https://via.placeholder.com/350x80/0000FF?Text=Banner01', 'https://via.placeholder.com/350x80/FF0000?Text=Banner02', 'https://via.placeholder.com/350x80/FFFF00?Text=Banner03', 'https://via.placeholder.com/350x80/000000?Text=Banner04', ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Container( child: Container( child: GridView.count( crossAxisCount: 2, childAspectRatio: 350/80, children: [for (final imageUrl in imageUrls) makeBanner(imageUrl)], )), )); } Widget makeBanner(String imageUrl) { return Image.network( imageUrl, ); } }