FlutterのExpandedウィジェットを使ってみる
ちょっと前にFlutterのMain AxisとCross Axisを一発で覚えるにはという記事を書いたんですが、今回はこれにExpandedを適用して使ってみようと思います。
環境
- macOS Big Sur 11.3.1
- Flutter 2.2.0
サンプル
以下の青色のContainerをみると青と緑の間にスペースが空いています。
ColumnのmainAxisAlignmentでMainAxisAlignment.spaceBetweenを指定している状態ですね。
まず、この空いたスペースを青で埋めるようにしたいと思います。
import 'package:flutter/material.dart';
class AxisSample extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Axis Sample'),
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 100,
color: Colors.red,
),
Container(
height: 100,
color: Colors.blue,
),
Container(
height: 100,
color: Colors.green,
)
],
),
),
);
}
}
高さを直接指定すると・・・
ちょっと青色のContainerのheightをいろいろ試してハードコーディングしても目的は達成できます。
import 'package:flutter/material.dart';
class AxisSample extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Axis Sample'),
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 100,
color: Colors.red,
),
Container(
// 値をいろいろ試した結果・・・
height: 507,
color: Colors.blue,
),
Container(
height: 100,
color: Colors.green,
)
],
),
),
);
}
}
もちろん、これは大きな問題があって画面の大きさが変わってしまえばあっという間に崩れてしまいます。
試しにPixel4で表示してみると・・・
間が空いてしまいます。
Expandedを使う
画面の大きさに合わせていい感じにスペースを埋めるにはExpandedを使えばよく、Expandedを青色のブロックに適用すると
- iPhone(iPhone12)
- Andorid(Pixel4)
画面のサイズに合わせてスペースを埋めてくれました。
Expandedをもう一つ増やした場合は?
Expandedの動きについて
Expandedがスペースを埋めるロジックですが公式ドキュメントを読むと、まずMainAxis が固定のWidgetを先に置いて、次に空いたスペースを埋めるように動きます。
ここまでの例でいうと、青色部分のみExpandedにしていましたが、
- 赤、緑ブロックを先に配置
- 空いたスペースを青で埋める
という順番で配置されていたということになりますね。
では、赤色部分もExpandedにするとどうなるでしょうか?試してみましょう。
import 'package:flutter/material.dart';
class AxisSample extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Axis Sample'),
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Container(
color: Colors.red,
),
),
Expanded(
child: Container(
color: Colors.blue,
),
),
Container(
height: 100,
color: Colors.green,
)
],
),
),
);
}
}
赤色のWidgetのheightを削除してExpandedで囲みました。エミュレータで確認してみると、
緑のブロック分を除いたスペースを1:1になるように配置されているのがわかります。さらにこの割合はExpandedのflexプロパティで変えることができます。
- 赤:青を1:2にする
import 'package:flutter/material.dart';
class AxisSample extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Axis Sample'),
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
// set flex property
flex: 1,
child: Container(
color: Colors.red,
),
),
Expanded(
// set flex property
flex: 2,
child: Container(
color: Colors.blue,
),
),
Container(
height: 100,
color: Colors.green,
)
],
),
),
);
}
}
最後に
画面の大きさに応じてWidgetの大きさを可変にしたいときにExpandedが役に立ちそうですね。
FlutterのWidgetはよくできていて、CSSみたいにデザインの細かい部分で試行錯誤しないでさっと画面が組めるので、私のようなバックエンド中心だったエンジニアでもそれっぽい画面ができてしまうので遊んでいて楽しいです😎







Discussion