Open3

Expandedとは?

muranakarmuranakar

はじめに

Flutterでレイアウトを作成する際、「残りのスペースを全て使いたい」「要素を特定の比率で配置したい」というケースがよくあります。そんな時に便利なのがExpandedウィジェットです。

Expandedとは

Expandedは、親のFlexible系ウィジェット(RowやColumn)の中で、利用可能な残りのスペースを埋めるために使用されるウィジェットです。

基本的な使い方

まずは最もシンプルな例を見てみましょう:

Row(
  children: [
    Container(
      width: 100,
      color: Colors.blue,
      child: Text('固定幅'),
    ),
    Expanded(
      child: Container(
        color: Colors.red,
        child: Text('残りのスペースを埋める'),
      ),
    ),
  ],
)

この例では、青いコンテナが固定幅の100を取り、赤いコンテナが残りの全スペースを占めます。

flexプロパティの活用

複数のExpandedを使用する場合、flexプロパティで空きスペースの分配比率を指定できます:

Row(
  children: [
    Expanded(
      flex: 2,  // 2/3のスペースを取る
      child: Container(
        color: Colors.blue,
        child: Text('2の比率'),
      ),
    ),
    Expanded(
      flex: 1,  // 1/3のスペースを取る
      child: Container(
        color: Colors.red,
        child: Text('1の比率'),
      ),
    ),
  ],
)

実践的なユースケース

よくある実装パターンを見てみましょう。例えば、リストビューのアイテムでタイトルと操作ボタンを配置する場合:

ListView.builder(
  itemBuilder: (context, index) {
    return ListTile(
      title: Row(
        children: [
          Expanded(
            child: Text(
              '長いタイトルテキストがはみ出さずに表示される',
              overflow: TextOverflow.ellipsis,
            ),
          ),
          IconButton(
            icon: Icon(Icons.edit),
            onPressed: () {},
          ),
        ],
      ),
    );
  },
)

注意点

  1. ExpandedはFlexible系の親ウィジェット内でのみ使用可能
  2. flexの値は1以上の整数である必要がある
  3. 兄弟要素にExpandedFlexibleがない場合、その要素は必要なスペースを優先的に確保する

応用テクニック

nested(入れ子)構造での使用例を見てみましょう:

Column(
  children: [
    Expanded(
      flex: 2,
      child: Row(
        children: [
          Expanded(
            child: Container(color: Colors.red),
          ),
          Expanded(
            child: Container(color: Colors.blue),
          ),
        ],
      ),
    ),
    Expanded(
      flex: 1,
      child: Container(color: Colors.green),
    ),
  ],
)

この例では、画面を上部2/3と下部1/3に分割し、さらに上部を左右均等に分割しています。

muranakarmuranakar

1. Flexibleウィジェットとは

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

Flexibleウィジェットは、Row、Column、またはFlexの子ウィジェットの伸縮性を制御するためのウィジェットです。

const Flexible({
  Key? key,
  int flex = 1,
  FlexFit fit = FlexFit.loose,
  required Widget child
})

主なプロパティ:

  • flex: 伸縮係数(デフォルト値: 1)
  • fit: 子ウィジェットの配置方法
  • child: 子ウィジェット

2. Flexibleの特徴

2.1 伸縮性の制御

Flexibleは、メイン軸方向(Rowの場合は水平方向、Columnの場合は垂直方向)に沿って、利用可能なスペースを柔軟に使用することができます。

Row(
  children: [
    Flexible(
      flex: 2,
      child: Container(color: Colors.blue),
    ),
    Flexible(
      flex: 1,
      child: Container(color: Colors.red),
    ),
  ],
)

上記の例では、青いコンテナが利用可能なスペースの2/3、赤いコンテナが1/3を占めます。

2.2 ExpandedとFlexibleの違い

重要な違いとして、Flexibleは以下の特徴があります:

  • 子ウィジェットに利用可能なスペースをすべて埋めることを強制しない
  • FlexFit.looseがデフォルト値として設定されている
// Flexibleの例
Row(
  children: [
    Flexible(
      child: Container(
        width: 100, // 指定したサイズが維持される
        color: Colors.blue,
      ),
    ),
  ],
)

3. 使用上の注意点

3.1 配置の制約

Flexibleウィジェットは以下の条件を満たす必要があります:

  • Row、Column、またはFlexの子孫である必要がある
  • Flexibleから親のRow/Column/Flexまでのパスには、StatelessWidgetまたはStatefulWidgetのみが含まれる必要がある
// 正しい使用例
Column(
  children: [
    Flexible(
      child: Container(),
    ),
  ],
)

// 誤った使用例(エラーとなる)
Container(
  child: Flexible( // Row/Column/Flexの子孫ではないためエラー
    child: Text('Error'),
  ),
)

3.2 FlexFitの設定

fitプロパティには2つの選択肢があります:

enum FlexFit {
  tight,  // 利用可能なスペースをすべて埋める
  loose,  // 子ウィジェットの希望するサイズを尊重
}

4. パフォーマンスと最適化

Flexibleウィジェットは軽量に設計されており、レイアウト計算に大きなオーバーヘッドを追加しません。ただし、以下の点に注意が必要です:

// 推奨される使用方法
Row(
  children: [
    Flexible(
      flex: 1,
      child: const SizedBox(), // const を使用して再構築を防ぐ
    ),
  ],
)