💬

FlutterのExpandedウィジェットを使ってみる

2021/07/10に公開

ちょっと前にFlutterのMain AxisとCross Axisを一発で覚えるにはという記事を書いたんですが、今回はこれにExpandedを適用して使ってみようと思います。

環境

  • macOS Big Sur 11.3.1
  • Flutter 2.2.0

サンプル

以下の青色のContainerをみると青と緑の間にスペースが空いています。
ColumnmainAxisAlignmentMainAxisAlignment.spaceBetweenを指定している状態ですね。

まず、この空いたスペースを青で埋めるようにしたいと思います。

Image from Gyazo

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,
            )
          ],
        ),
      ),
    );
  }
}

高さを直接指定すると・・・

ちょっと青色のContainerheightをいろいろ試してハードコーディングしても目的は達成できます。

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,
            )
          ],
        ),
      ),
    );
  }
}

Image from Gyazo

もちろん、これは大きな問題があって画面の大きさが変わってしまえばあっという間に崩れてしまいます。
試しにPixel4で表示してみると・・・

Image from Gyazo

間が空いてしまいます。

Expandedを使う

画面の大きさに合わせていい感じにスペースを埋めるにはExpandedを使えばよく、Expandedを青色のブロックに適用すると

  • iPhone(iPhone12)

Image from Gyazo

  • Andorid(Pixel4)

Image from Gyazo

画面のサイズに合わせてスペースを埋めてくれました。

Expandedをもう一つ増やした場合は?

Expandedの動きについて

Expandedがスペースを埋めるロジックですが公式ドキュメントを読むと、まずMainAxis が固定のWidgetを先に置いて、次に空いたスペースを埋めるように動きます。

ここまでの例でいうと、青色部分のみExpandedにしていましたが、

  1. 赤、緑ブロックを先に配置
  2. 空いたスペースを青で埋める

という順番で配置されていたということになりますね。
では、赤色部分も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で囲みました。エミュレータで確認してみると、

Image from Gyazo

緑のブロック分を除いたスペースを1:1になるように配置されているのがわかります。さらにこの割合はExpandedflexプロパティで変えることができます。

  • 赤:青を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,
            )
          ],
        ),
      ),
    );
  }
}

Image from Gyazo

最後に

画面の大きさに応じてWidgetの大きさを可変にしたいときにExpandedが役に立ちそうですね。
FlutterのWidgetはよくできていて、CSSみたいにデザインの細かい部分で試行錯誤しないでさっと画面が組めるので、私のようなバックエンド中心だったエンジニアでもそれっぽい画面ができてしまうので遊んでいて楽しいです😎

参考

Discussion