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