🐺

【Flutter Widget】「FittedBox」を学ぼう

2022/11/11に公開約7,200字1件のコメント

こんにちは、Saeです。
私は「さえないエンジニア」から「さえたエンジニア」へクラスチェンジするために、日々レベル上げに勤しんでます。
今日は「FittedBox」というWidgetについて解説していきます。

また今回使用しているサンプルコードはGithubで公開しております。参考になれば幸いです。
https://github.com/Sae-Eng/fitted_box_example

この記事で書いてあること

  • 忙しい人のための「FittedBox」
  • FittedBoxとは
  • FittedBoxはどういう動きをするのか
  • 「Fit」でスケーリングの手法を変える方法

忙しい人のための「FittedBox」

日々忙しさで忙殺されているエンジニアへ向けた「FittedBox」の説明です。
ここだけ見れば、なんとなくわかります。

FittedBoxで囲ったら、親Widgetに合わせてスケーリング
Fitプロパティでスケーリング方法が変わる

FittedBoxとは

それではここから詳しく「FittedBox」について説明していきます。

そもそもFittedBoxとは何なのでしょうか。
公式ドキュメントには以下のように記載されてます。

fit に従って子をスケールし、ウィジェット内に配置するウィジェットを作成します。

https://api.flutter.dev/flutter/widgets/FittedBox-class.html

要はFittedBoxで囲った子要素を、
親要素に合わせてスケーリング(自動的に拡大・縮小)させるWidget
ということですね。

FittedBoxはどういう動きをするのか

では実際のコードと実行結果を見ながら、FittedBoxはどういう動きをするのか見ていきましょう。

Fitted box 非適用

// 親Widget(Container)
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: containerWidth,
  height: containerHeight,
  // 子Widget(Text)
  child: const Text(
    'Fitted Box is not applied',
    style: TextStyle(
      backgroundColor: Colors.greenAccent,
    ),
  ),
),

Fitted box 適用

// 親Widget(Container)
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: containerWidth,
  height: containerHeight,

  // FittedBox
  // 親WidgetのContainerに合わせて、FittedBoxの子Widget(Text)がスケーリングする
  child: const FittedBox(
    // 子Widget(Text)
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

実行結果

実行結果から、親WidgetのContainerに合わせて、
FittedBoxの子Widget(Text)がスケーリングしていることがわかったかと思います。

「Fit」を使って、スケーリングの手法を変えよう

FittedBoxでは、FItというプロパティを変えることでスケーリングの手法を変えることができます。

Fitの種類は以下になります。

プロパティ名 実際の動き
fill アスペクト比を変えて、親要素の幅・高さに合わせる
contain 親要素内におさめ、また子要素のアスペクト比を崩さずに可能な限り大きくする
cover 親要素全体を埋めつつ、子要素のサイズをできるだけ小さくする
fitWidth 親要素から垂直方向にはみ出しても、子要素の幅はおさまるように表示する
fitHeight 親要素から水平方向にはみ出しても、子要素の高さはおさまるように表示する
none 子要素を親要素に配置(デフォルトはセンタリング)し、親要素の外部分はすべて破棄して表示する
scaleDown 子要素を親要素に配置(デフォルトはセンタリング)し、必要に応じて小さくおさまるように表示

文面だけだとイメージがつきにくいと思うので、
最後に実際のコードと実行結果を確認しながら、挙動を確認していきましょう。

Fill

  • アスペクト比を変えて、親要素の幅・高さに合わせる
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: containerWidth,
  height: containerHeight,
  child: const FittedBox(
		// fill: アスペクト比を変えて、親要素の幅・高さに合わせる
    fit: BoxFit.fill,
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

contain

  • 親要素内におさめ、また子要素のアスペクト比を崩さずに可能な限り大きくする
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: containerWidth,
  height: containerHeight,
  child: const FittedBox(
		// contain: 親要素内におさめ、また子要素のアスペクト比を崩さずに可能な限り大きくする
    fit: BoxFit.contain,
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

cover

  • 親要素全体を埋めつつ、子要素のサイズをできるだけ小さくする
    • はみ出した部分を切り取る場合は、clipBehaviorプロパティを使用する
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 100,
  height: 25,
  child: const FittedBox(
		// cover: 親要素全体を埋めつつ、子要素のサイズをできるだけ小さくする
    fit: BoxFit.cover,
    // はみ出した部分を切り取る場合は、clipBehaviorプロパティを使用する
    clipBehavior: Clip.hardEdge,
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

fitWidth

  • 親要素から垂直方向にはみ出しても、子要素の幅はおさまるように表示する
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 150,
  height: 50,
  child: const FittedBox(
		// fitWidth: 親要素から垂直方向にはみ出しても、子要素の幅はおさまるように表示する
    fit: BoxFit.fitWidth,
    child: Text(
      'Apply Fitted\r\nBox',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

fitHeight

  • 親要素から水平方向にはみ出しても、子要素の高さはおさまるように表示する
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 100,
  height: 75,
  child: const FittedBox(
		// fitHeight: 親要素から水平方向にはみ出しても、子要素の高さはおさまるように表示する
    fit: BoxFit.fitHeight,
    child: Text(
      'Apply Fitted\r\nBox',
      style: TextStyle(
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

none

  • 子要素を親要素に配置(デフォルトはセンタリング)し、親要素の外部分はすべて破棄して表示する
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 50,
  height: 50,
  child: FittedBox(
		// none: 子要素を親要素に配置(デフォルトはセンタリング)し、親要素の外部分はすべて破棄して表示する
    fit: BoxFit.none,
    child: Text(
      'Apply Fitted\r\nBox',
      style: TextStyle(
        fontSize: 25,
        backgroundColor: Colors.greenAccent.withOpacity(0.5),
      ),
    ),
  ),
),

scaleDown

  • 子要素を親要素に配置(デフォルトはセンタリング)し、必要に応じて小さくおさまるように表示
// Container 小サイズ
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 100,
  height: 50,
  child: const FittedBox(
		// scaleDown: 子要素を親要素に配置(デフォルトはセンタリング)し、必要に応じて小さくおさまるように表示
    fit: BoxFit.scaleDown,
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        fontSize: 100,
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),
// Container 大サイズ
Container(
  decoration: BoxDecoration(
    border: Border.all(
      width: 4,
      color: Colors.blueAccent,
    ),
  ),
  width: 200,
  height: 50,
  child: const FittedBox(
		// scaleDown: 子要素を親要素に配置(デフォルトはセンタリング)し、必要に応じて小さくおさまるように表示
    fit: BoxFit.scaleDown,
    child: Text(
      'Apply Fitted Box',
      style: TextStyle(
        fontSize: 100,
        backgroundColor: Colors.greenAccent,
      ),
    ),
  ),
),

Discussion

ちょうど調べたいなぁ〜って思ってたところなので非常に有難いですmm

ログインするとコメントできます