Expanded:とは何か、Flutterでの動作原理

著者: IT Sectr 公開日: 2026-07-03 読了時間: 6 分

Expandedは、子要素にFlexコンテナ内の利用可能なすべてのスペースを埋めさせるFlutterウィジェットです。RowやColumnが子要素間でスペースを分配する際、Expandedは非フレキシブル要素を考慮した後の空きスペースを取得します。公式Flutterドキュメント(2026年)によると、Expandedは最も使用されているレイアウトウィジェットの1つであり、パーセンテージベースのインターフェース、カード、リスト、パネルの構築に適用されています。その主な利点は、寸法を明示的に指定せずに、flex係数に基づいて幅または高さを自動計算することです。

重要なポイント

  • Expandedは、Row、Column、Flex内で子を拡張して利用可能なすべてのスペースを埋めるレイアウトウィジェットです
  • Flex係数は、各Expandedが受け取る空きスペースの割合を決定します
  • Expandedは、利用可能なすべてのスペースを強制的に埋める点でFlexibleと異なります
  • StackはExpandedをサポートしておらず、Row、Column、Flexのみがサポートします
  • エラー:Flexコンテナ外でExpandedを使用するとLayoutExceptionが発生します

Expandedとは

Expandedは、子を受け取り、Flexコンテナ(Row、Column、Flex)内の利用可能なスペースを埋めるように強制するラッパーウィジェットです。Expandedには独自の視覚的表現はありません—子要素に渡される制約(constraints)のみを管理します。

Expandedの核心は、Flutterフレームワークが提供するFlexメカニズムです。RowやColumnが子のサイズを計算するとき、最初に非フレキシブル要素(固定サイズの通常ウィジェット)にスペースを割り当て、残りのスペースをExpandedとFlexibleの子の間にそれらのflex係数に比例して分配します。

ExpandedはFlexible.fit = FlexFit.tightを使用します。これは、Expandedの子が、自身のサイズが小さくても、割り当てられたすべてのスペースを占有しなければならないことを意味します。子が割り当てられた領域より小さくてもよいFit.looseのFlexibleとは異なり、Expandedはコンテンツを強制的に拡張します。

まとめ:Expandedは、Flutterで比例レイアウトを作成するための主要なツールです。要素が利用可能なすべての幅または高さを確実に埋める必要がある場合に使用します。

Expanded vs Flexible:主な違い

ExpandedFlexibleはどちらもFlexコンテナ内でスペースを分配しますが、根本的に異なる動作をします。違いはfitプロパティにあり、子が利用可能なスペースより小さくなれるかどうかを決定します。

Expandedは厳格な動作モデルを持っています:そのfitはFlexFit.tightです。これは、子ウィジェットが利用可能なスペースと等しい制約を受け取ることを意味します—それ以上でもそれ以下でもありません。子が小さければ拡張され、大きければ縮小されます。FlexibleはFlexFit.looseを使用し、子要素が割り当てられたスペース内で任意のサイズになることを許可します。

実際には:Row内にflex=1のExpandedが2つある場合、それぞれが正確に半分の幅を占有します。それらをfit.looseのFlexibleに置き換えると、各子は自身のサイズが小さければ半分より小さくなる可能性があり、残りのスペースは空のままになります。

まとめ:厳格な比例レイアウトにはExpandedを使用し、子が利用可能なスペースより小さくてもよい場合はFlexibleを使用します。不明な場合はExpandedから始めてください。より予測可能な動作を提供します。

Flex係数:スペースの分配方法

Flex係数(flexパラメータ)は、Expandedが受け取る利用可能なスペースの割合を決定する数値です。デフォルトではflex=1で、すべてのExpandedの子間で均等に分配されます。

分配アルゴリズムは3つのステップで動作します。第一に:Flutterはすべての非フレキシブル子の内在サイズを計算します。第二に:残りのスペースをすべてのflex係数の合計で割ります。第三に:各Expandedは、自身のflex係数に1つのflex単位のサイズを掛けた値に等しいシェアを受け取ります。

例えば、幅300pxのRowに2つのExpandedが含まれている場合:最初がflex=2、2番目がflex=1です。空きスペース(300pxから非フレキシブル子を引いたもの)は3つの部分に分割されます。最初が2/3を受け取り、2番目が1/3を受け取ります。非フレキシブル子がない場合、最初は200px、2番目は100pxを受け取ります。

Flex係数は任意の正の整数にできます。値0は特別なケースです:flex=0のExpandedは通常の非フレキシブルウィジェットのように動作し、子のサイズに従って最小限のスペースを占有します。この動作はExpandedがない場合と同等です。

まとめ:flex係数は、柔軟なレイアウトを構築するための鍵です。等しいカラムには1:1、メインエリアとサイドバーエリアのあるパネルには2:1、狭いナビゲーションのインターフェースには3:1の比率を使用します。

Expandedを使用したコード例

例1は、3つの等しいカラムを作成するためのRowでのExpandedの基本的な使用法を示しています。

dart
Row(
  children: [
    Expanded(
      child: Container(
        color: Colors.red,
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.green,
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.blue,
      ),
    ),
  ],
)

この例では、3つのExpanded(デフォルトでflex=1)がRowの幅を均等に分割しています。コンテナはRowによって設定された全高に拡張され、等しいシェアを占有します。このアプローチは、比例配分によるカラムベースのレイアウトを作成するのに便利です。

例2は、サイドバーとメインコンテンツを持つレイアウトを作成するために異なるflex係数を使用する方法を示しています。

dart
Row(
  children: [
    Expanded(
      flex: 1,
      child: Container(
        color: Colors.grey.200,
        child: const Center(
          child: Text('サイドバー'),
        ),
      ),
    ),
    Expanded(
      flex: 3,
      child: Container(
        color: Colors.white,
        child: const Center(
          child: Text('コンテンツエリア'),
        ),
      ),
    ),
  ],
)

2番目の例は、サイドバー(25%)とメインコンテンツエリア(75%)を持つ典型的なレイアウトを作成します。flex=1とflex=3は1:3の比率を与えます。画面幅が変わると、比率は自動的に保持されます—これがレスポンシブインターフェースの基盤です。

まとめ:異なるflex係数を持つExpandedは、レスポンシブレイアウトを構築するための標準ツールです。ColumnでExpandedを組み合わせることで、水平と垂直の両方の比例配置を作成できます。

Expanded使用時の一般的な間違い

間違い1:Row、Column、Flexの外でExpandedを使用する。ExpandedをStack、ListView、または他の非Flexコンテナに直接配置すると、Flutterは「Expanded widgets must be placed inside Flex widgets」というメッセージのLayoutExceptionをスローします。解決策:親ウィジェットを確認します—Row、Column、Flexのみです。

間違い2:shrinkWrapを指定せずにListView内にExpandedを配置する。ListViewはデフォルトでスクロール方向に無限の高さを持ち、Expandedは自分のシェアを計算できません。解決策:shrinkWrap: trueを使用するか、ListViewを固定高さのSizedBoxでラップします。

間違い3:合計flexが利用可能なスペースを超える複数のExpanded。制限された幅のRowにExpandedと大きな内在サイズのウィジェットが含まれている場合、オーバーフローが発生する可能性があります。解決策:非フレキシブル子の最小サイズを確認し、必要に応じてFittedBoxまたはFlex fitを使用します。

間違い4:Row内のColumnにネストされたExpanded。Column内のExpandedがRow内に別のExpandedを含む場合、制約の競合が発生する可能性があります。解決策:ネストの深さを制限するか、中間レベルで明示的に寸法を設定するためにConstrainedBoxを使用します。

まとめ:Expandedには正しい親コンテキストが必要です。Expandedが直接Row、Column、Flexに配置されていることを常に確認し、明示的な寸法なしのネストを避けてください。

よくある質問

ExpandedはSizedBox.expandとどう違うのですか?

SizedBox.expandは外部制約によって設定された寸法に子を強制的に拡張しますが、flex配分には参加しません。ExpandedはFlexコンテナ内でのみ機能し、子間の空きスペースを分配する際にflex係数を考慮します。

Stack内でExpandedを使用できますか?

いいえ。StackはFlexコンテナではなく、内部でExpandedを使用するとLayoutExceptionが発生します。Stackで子を拡張するには、Positioned.fillまたはBoxConstraints.expandを使用してください。

flex係数を指定しないとどうなりますか?

デフォルトではflex=1です。明示的なflexなしのすべてのExpandedは、空きスペースの等しいシェアを受け取ります。Rowにflexなしの3つのExpandedがある場合、各々が利用可能なスペースのちょうど3分の1を占有します。

Expandedを幅のみで高さなしにするには?

水平方向の拡張にはExpandedをRowに配置します。垂直方向の拡張にはColumn内でExpandedを使用します。寸法を制限する必要がある場合は、Expandedまたはその子をSizedBoxでラップします。

ExpandedはWrapやFlexウィジェットで動作しますか?

ExpandedFlexで動作し、RowとColumnをそのサブクラスとして含みます。WrapはFlexコンテナではなく、Expandedをサポートしていません。Wrapでスペースを分配するには、RunAlignmentなどの他の方法を使用してください。

まとめ

  • Expandedは、Flexコンテナ内で利用可能なすべてのスペースを埋めるように子を強制的に拡張するウィジェットです
  • Flex係数は、複数のExpanded間での空きスペース配分の比率を決定します
  • Flexibleとの違い:Expandedはtight fit(強制充填)、Flexibleはloose fit(オプション)を使用します
  • エラー:Row、Column、Flexの外にExpandedを配置するとLayoutExceptionが発生します
  • レスポンシブ性:画面サイズが変更されてもレイアウト比率は自動的に保持されます
  • 推奨:Flutterのカラムおよびパネルレイアウトの主要ツールとしてExpandedを使用してください

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください