Flutterを使ってみよう その8(レイアウト方法②)

前回の続きで他のレイアウトについて、触れていきたいと思います。

環境

 ・MacOS Ventura 13.6.3
 ・Xcode 15.1
 ・VSCode 1.85.1
 ・Flutter 3.16.5
 ・Dart 3.2.3

1. OverflowBox ウィジェット


OverflowBox ウィジェットは、親の幅・高さ制約を超える制約を子ウィジェットへ制約設定するときに使うレイアウトウィジェットです。

SafeArea(
  child: Align(
    alignment: Alignment.center,
    child: Container(
      width: 200,
      height: 200,
      color: Colors.grey,
      child: const OverflowBox(
        maxWidth: 300,
        maxHeight: 300,
        child: FlutterLogo(size: 300),
      ),
    ),
  ),
),

コード例だと、 OverflowBox ウィジェットを使用して、幅200×高さ200の領域の親ウィジェットに対して、それを超える幅300×高さ300までの領域内で子ウィジェット( FlutterLogo ウィジェット)を表示します。

2. SizedOverflowBox ウィジェット


SizedOverflowBox ウィジェットは、子ウィジェットが幅・高さの制約を超過して表示することを許可するときに使うレイアウトウィジェットです。

SafeArea(
  child: Align(
    alignment: Alignment.center,
    child: Container(
      width: 200,
      height: 200,
      color: Colors.grey,
      child: Center(
        child: SizedOverflowBox(
          alignment: Alignment.topCenter,
          size: const Size(100, 100),
          child: Container(
            width: 150,
            height: 20,
            color: Colors.blue,
          ),
        ),
      ),
    ),
  ),
),

コード例だと、 SizedOverflowBox ウィジェットを使用して、幅100×高さ100の領域ではありますが、子ウィジェットは、幅150×高さ50の青の領域ですので、 alignment 位置に従い、超過して表示します。

ただし、親ウィジェットは、幅200×高さ200の領域に対して、超過して表示することはできまません。

3. FractionallySizedBox ウィジェット


FractionallySizedBox ウィジェットは、子ウィジェットへの幅・高さの比率による制約設定するときに使うレイアウトウィジェットです。

SafeArea(
  child: SizedBox.expand(
    child: FractionallySizedBox(
      widthFactor: 0.5,
      heightFactor: 0.5,
      alignment: FractionalOffset.center,
      child: ColoredBox(
        color: Colors.blue,
      ),
    ),
  ),
),

コード例だと、FractionallySizedBox ウィジェットを使用して、親ウィジェットに対して、幅、高さ50%の領域で中央位置時配置で、青の領域を表示します。

親ウィジェットは、 SizedBox.expand で生成したウィジェットです。

4. AspectRatio ウィジェット


AspectRatio ウィジェットは、子ウィジェットへの幅・高さをアスペクト比による制約設定するときに使うレイアウトウィジェットです。

SafeArea(
  child: Container(
    color: Colors.grey,
    alignment: Alignment.center,
    height: 100,
    child: AspectRatio(
      aspectRatio: 16 / 9,
      child: Container(
        color: Colors.blue,
      ),
    ),
  ),
),

コード例だと、親ウィジェットは、高さ100の領域(幅は、横一杯)の灰色の領域に対し、AspectRatio ウィジェットを使用して、子ウィジェットが、幅:高さのアスペクト比が16:9で、中央位置で、青の領域を表示します。

青の領域の高さは、親の高さを継承しており、幅は、アスペクト比により計算されます。(計算結果は、100 * 16 / 9 = 約178)

SafeArea(
  child: Align(
    alignment: Alignment.topCenter,
    child: Container(
      color: Colors.grey,
      alignment: Alignment.center,
      width: 100,
      height: 100,
      child: AspectRatio(
        aspectRatio: 2,
        child: Container(
          width: 50,
          height: 20,
          color: Colors.blue,
        ),
      ),
    ),
  ),
),
</code></pre>

コード例だと、親ウィジェットは、幅、高さともに100の領域の灰色の領域に対し、青の領域を指定サイズでは幅50×高さ20を指定にしていますが、 AspectRatio ウィジェットの制約が優先されます。

そのため、幅:高さのアスペクト比を2:1で調整するため、幅100×高さ50になり、中央位置で表示されます。

<pre><code>
SafeArea(
  child: Align(
    alignment: Alignment.topCenter,
    ch

5. FittedBoxウィジェット


FittedBox ウィジェットは、子ウィジェットへのフィット指定による制約設定するときに使うレイアウトウィジェットです。

SafeArea(
  child: Align(
    alignment: Alignment.topCenter,
    child: Container(
      color: Colors.blue,
      width: 200,
      height: 300,
      child: const FittedBox(
        fit: BoxFit.fill,
        child: Placeholder(),
      ),
    ),
  ),
),

コード例だと、 FittedBox ウィジェットを使用して、親ウィジェットの幅200×高さ300の青の領域に対し、 Placeholder ウィジェットを領域一杯に広げるように表示されます。

ターゲットになるウィジェットのフィット感の指定は、引数 fit で指定し、ターゲットがはみ出し表示するときのクリッピング指定は、引数 clipBehavior で指定します。


fit の内容は、下記の通りです。

 ・BoxFit.fill :アスペクト比無視し、ターゲットを領域一杯に配置

 ・BoxFit.contain :アスペクト比を保ちながら、ターゲットを領域内に配置

 ・BoxFit.fitWidth :アスペクト比を保ちながら、ターゲットを幅基準で配置(場合によっては、はみ出る)

 ・BoxFit.fitHeight :アスペクト比を保ちながら、ターゲットを高さ基準で配置(場合によっては、はみ出る)

 ・BoxFit.cover :アスペクト比を保ちながら、ターゲットを幅基準、または、高さ基準で配置(場合によっては、はみ出る)

 ・BoxFit.scaleDown :ターゲットのサイズ感で配置し、はみ出る場合は、アスペクト比を保ちながら、ターゲットを領域内に配置

 ・BoxFit.none :ターゲットのサイズ感で配置(場合によっては、はみ出る)


clipBehavior の内容は、下記の通りです。

 ・Clip.hardEdge :はみ出し内容は、切り落とし(一般的なクリッピング)

 ・Clip.antiAlias :はみ出し内容は、切り落とし(アンチエイリアシング使用)

 ・Clip.antiAliasWithSaveLayer :はみ出し内容は、切り落とし(アンチエイリアシング+レイヤークリップ)

 ・Clip.none :何もしなし

※目視では、 Clip.hardEdge、 Clip.antiAlias、 Clip.antiAliasWithSaveLayer の違いはわかりませんでした。

6. まとめ

今回は、続きでレイアウトの知識を深めるのを目的に記事を書きました。

今まで、子ウィジェットが単一の場合のレイアウト制御で、他にもありますが、一旦、次回から、複数の子ウィジェットのレイアウトやそれらを使った応用した例などでレイアウトの知識を深める予定です。