Flutterその他

【Flutter】レイアウト調整に使うWidget解説(SizedBox, Expanded)

Flutter
この記事は約8分で読めます。

はじめに

株式会社インプルの渡部です。

Flutterでの実務経験が1年になるのでこれまでの実装経験から「このWidgetはこういう風に使うことが多いな」というのを少しずつまとめていこうと思います。

今回はアプリのレイアウト調整によく使うSizedBoxとExpanded についてです。

SizedBox

SizedBoxは簡単に説明すると指定されたサイズの透明な箱です。

SizedBoxの幅や高さを指定することでchildに指定したWidgetを任意の大きさに設定することが出来ます。

サンプルコード

では、実際にコードと実行画面をみてsizedBoxの動きを確認してみましょう。

サンプルコード(比較対象のボタン部分のみ抜粋)

//sizedBoxなし
TextButton(
  onPressed: () {},
  style: TextButton.styleFrom(
   side: const BorderSide(
   color: Colors.black,
   width: 5,
   ),
  ),
  child: const Text("button(sizedBoxなし)"),
),

//sizedBoxあり
SizedBox(
  width: 300,
  height: 150,
  child: TextButton(
   onPressed: () {},
   style: TextButton.styleFrom(
    side: const BorderSide(
    color: Colors.black,
    width: 5,
    ),
  ),
  child: const Text("button(sizedBoxあり)")),
)

添付のコードはSizedBoxありとなしのボタンのコードです。ボタンは範囲が分かりやすいように黒色の枠線で囲っています。実行した画面を確認するとSizedBoxなしのボタンはテキスト部分のみがボタンの範囲になっていますがSizedBoxありのボタンはテキスト部分以外も囲われています。ボタン部分のコードは全て同じですがSizedBoxに囲われているか否かでボタンの範囲が変わっていることからSizedBoxがchildに指定したWidgetを任意の大きさに設定しているというのが分かると思います。

SizedBoxのコンストラクタ

SizedBoxには4種類のコンストラクタがあるのでこちらもおまけで軽く紹介しておきます。

SizedBox.expanded

親Widgetが許容する最大サイズのボックスを作成します。

width,heightにはdouble.infinityが設定されていて親Widgetの余白部分を埋めてくれます。

const SizedBox.expand({ super.key, super.child })
  : width = double.infinity,
    height = double.infinity;

SizedBox.fromSize

指定したサイズのボックスを作成します。

sizeプロパティからwidthとheightを自分で設定することが出来ます。

SizedBox.fromSize({ super.key, super.child, Size? size })
  : width = size?.width,
    height = size?.height;

SizedBox.Shrink

親Widgetが許容する最小サイズのボックスを作成します。

width,heightには0が設定されます。

const SizedBox.shrink({ super.key, super.child })
  : width = 0.0,
    height = 0.0;

SizedBox.square

幅と高さが等しいボックスを作成します。

Dimensionプロパティからdouble型の値を設定します。

const SizedBox.square({super.key, super.child, double? dimension})
  : width = dimension,
    height = dimension;

実務ではどうやって使うの?

この1年間で使ったのはコンストラクタなしのSizedboxのみでした。

SizedBoxの使用場面としてはサンプルコードで紹介したようなButtonなどWidgetの幅・高さの設定のほかにWidgetを縦や横に並べたときのWidget間の余白をとるために使うことが多かったです。Widget間の余白をとるためのコードに付いてもサンプルコードを添付します。実行画面の赤枠部分が該当部分です。ColumnやRowでWidgetを縦や横に配置した際に余白をとるために使うことが多いと思うのでこちらの使い方も覚えておきましょう。

Widget間の余白のためのSizedBox
Column(
  children: [
   const Text("SizedBoxなし"),
   TextButton(
    onPressed: () {},
    style: TextButton.styleFrom(
     side: const BorderSide(
      color: Colors.black,
      width: 5,
     ),
    ),
    child: const Text("button(SizedBoxなし)"),
   ),
   //余白のためのSizedBox Widget
   const SizedBox(
    height: 32,
   ),
   const Text("SizedBoxあり"),
   SizedBox(
    width: 300,
    height: 150,
    child: TextButton(
     onPressed: () {},
     style: TextButton.styleFrom(
      side: const BorderSide(
       color: Colors.black,
       width: 5,
      ),
     ),
    child: const Text("button(SizedBoxあり)")),
   )
  ],
),

4種類のコンストラクタについては今後使用することがあればどのような場面で使用したかをまとめて追記しようと思います。

Expanded

RowやColumnの子Widget間の隙間をすべて埋めたいときに使います。

Expanded Widget使用の注意点として必ずColumn, Row, Flex Widgetの子孫Widgetでないといけません。

サンプルコード

では、Expandedについても実際にコードと実行画面をみて動きを確認してみましょう。

サンプルコード(比較対象部分のみ抜粋)

//Expandedなし
Row(
  children: const [
   ColoredBox(color: Colors.blue, child: Text('Box1')),
   ColoredBox(color: Colors.yellow, child: Text('Box2')),
  ],
),

//Expandedあり
Row(
  children: const [
   ColoredBox(color: Colors.blue, child: Text('Box1')),
   Expanded(
    child: ColoredBox(
     color: Colors.yellow, child: Text('Box2(Expanded)'))),
  ],
),

添付のコードはExpandedありとなしのコードです。実行画面確認するとExpandedありとなしでWidgetを横並びにしたときの結果が異なることが確認できます。このようにExpandedで囲むことでRowで横並びにした際に生じる余白部分をExpandedで囲んだwidgetの範囲に含めることができます。これはColumnで縦並びにしても同様の結果となります。

実務ではどうやって使うの?

実務でもサンプルコードのような使い方をしますが並べるWidgetは3つ以上でより複雑な実装が多いです。1例としてサンプルコードのような画面両端にWidgetを配置したいときなど全Widgetの幅を固定してしまうとデバイスが変わったらデザイン崩れが起きてしまうので真ん中部分はExpandedで幅を可変にするという形はよく見ると思います。


Row(
  children: const [
   ColoredBox(color: Colors.blue, child: Text('Box1')),
   Expanded(
    child: ColoredBox(
     color: Colors.yellow, child: Text('Box2(Expanded)'))
   ),
   ColoredBox(color: Colors.blue, child: Text('Box3')),
  ],
)

まとめ

今回はFlutterのレイアウト調整によく使うWidget 2つを紹介しました。

画面実装においてSizedBoxとExpanded Widgetは避けては通れないWidgetです。今回の記事が少しでも参考になればと思います。

ここまで読んでいただきありがとうございます。

参考

SizedBox class - widgets library - Dart API
API docs for the SizedBox class from the widgets library, for the Dart programming language.
Expanded class - widgets library - Dart API
API docs for the Expanded class from the widgets library, for the Dart programming language.