Skip to content

Expanded / Flexible

ExpandedFlexible 用于在 RowColumn 中让子组件按比例分配剩余空间

Expanded

构造函数

dart
Expanded({
  Key? key,                    // 组件标识
  int flex = 1,                // 弹性系数(按比例分配空间的权重)
  required Widget child,       // 子组件(必填)
})

属性速查

属性类型默认值说明
flexint1弹性系数,多个 Expanded 时按此比例分配剩余空间
childWidget必填子组件

快速示例

占满剩余空间

dart
import 'package:flutter/material.dart';

class ExpandedBasicExample extends StatelessWidget {
  const ExpandedBasicExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Expanded 基本用法')),
      body: Row(
        children: [
          Container(width: 100, color: Colors.red),    // 固定 100
          // ─── ★ 占满剩余空间 ──────────────
          Expanded(
            child: Container(color: Colors.blue),
          ),
          // ─── ☆ 占满剩余空间 ──────────────
        ],
      ),
    );
  }
}

按比例分配(flex)

dart
import 'package:flutter/material.dart';

class ExpandedFlexExample extends StatelessWidget {
  const ExpandedFlexExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Expanded flex 比例')),
      body: Row(
        children: [
          // ─── ★ flex 比例分配 ──────────────
          Expanded(
            flex: 1,                      // 占 1/3
            child: Container(color: Colors.red),
          ),
          // ─── ☆ flex 比例分配 ──────────────
          // ─── ★ flex: 2 ──────────────
          Expanded(
            flex: 2,                      // 占 2/3
            child: Container(color: Colors.blue),
          ),
          // ─── ☆ flex: 2 ──────────────
          // 总比例 = 1 + 2 = 3,红色占 1/3,蓝色占 2/3
        ],
      ),
    );
  }
}

Column 中的 Expanded

dart
import 'package:flutter/material.dart';

class ExpandedColumnExample extends StatelessWidget {
  const ExpandedColumnExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Column 中的 Expanded')),
      body: Column(
        children: [
          Container(height: 100, color: Colors.red),     // 固定 100
          // ─── ★ Column 中占满剩余高度 ──────────────
          Expanded(
            child: Container(color: Colors.blue),
          ),
          // ─── ☆ Column 中占满剩余高度 ──────────────
          Container(height: 50, color: Colors.green),     // 固定 50
        ],
      ),
    );
  }
}

Flexible

FlexibleExpanded 更灵活,可以控制子组件是「占满」还是「包裹」。

构造函数

dart
Flexible({
  Key? key,                       // 组件标识
  int flex = 1,                   // 弹性系数(按比例分配空间的权重)
  FlexFit fit = FlexFit.loose,    // 填充模式:loose=可小于分配空间,tight=必须填满
  required Widget child,           // 子组件(必填)
})

属性速查

属性类型默认值说明
flexint1弹性系数,多个 Flexible 时按此比例分配剩余空间
fitFlexFitloose填充模式
childWidget必填子组件

fit 参数

行为
FlexFit.loose子组件可以小于分配到的空间(默认)
FlexFit.tight子组件必须填满分配到的空间(= Expanded)

Flexible vs Expanded 对比

dart
// Flexible loose —— 子组件可以小于剩余空间
Flexible(
  fit: FlexFit.loose,  // 默认值
  child: Container(
    width: 80,         // 宽度 80,不强制填满剩余空间
    height: 50,
    color: Colors.red,
  ),
)

// Flexible tight —— 子组件必须填满剩余空间(等价于 Expanded)
Flexible(
  fit: FlexFit.tight,
  child: Container(height: 50, color: Colors.blue),
)

// Expanded —— 就是 Flexible tight 的快捷方式
Expanded(
  child: Container(height: 50, color: Colors.blue),
)

Expanded vs Flexible vs Spacer 速查

特性ExpandedFlexibleSpacer
本质Flexible(fit: tight)灵活的弹性组件空的 Expanded
子组件是否填满分配空间可选(由 fit 决定)无子组件
使用场景强制填满剩余空间需要子组件自适应大小纯占位间距
常用度⭐⭐⭐ 最常用⭐ 偶尔用⭐⭐ 方便

常见模式

权重分配

dart
Row(
  children: [
    Expanded(flex: 3, child: _buildCard('重要', Colors.red)),
    const SizedBox(width: 8),
    Expanded(flex: 2, child: _buildCard('一般', Colors.orange)),
    const SizedBox(width: 8),
    Expanded(flex: 1, child: _buildCard('低', Colors.green)),
  ],
)
// 比例:3 : 2 : 1

固定宽度 + 弹性宽度

dart
Row(
  children: [
    // 固定图标
    const SizedBox(
      width: 48,
      height: 48,
      child: Icon(Icons.search),
    ),
    // 弹性输入框
    Expanded(
      child: TextField(
        decoration: InputDecoration(
          hintText: '搜索...',
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(8),
          ),
        ),
      ),
    ),
    // 固定按钮
    SizedBox(
      width: 48,
      height: 48,
      child: IconButton(
        icon: const Icon(Icons.clear),
        onPressed: () {},
      ),
    ),
  ],
)

底部按钮行

dart
Row(
  children: [
    Expanded(
      child: OutlinedButton(
        onPressed: () {},
        child: const Text('取消'),
      ),
    ),
    const SizedBox(width: 16),
    Expanded(
      child: ElevatedButton(
        onPressed: () {},
        child: const Text('确认'),
      ),
    ),
  ],
)

用 Spacer 添加间距

dart
Row(
  children: [
    const Text('左边'),
    const Spacer(),              // 等价于 Expanded(child: SizedBox())
    const Text('右边'),
  ],
)

// Spacer 也支持 flex
Row(
  children: [
    const Text('A'),
    const Spacer(flex: 1),
    const Text('B'),
    const Spacer(flex: 2),
    const Text('C'),
  ],
)
// A  [  间距  ]  B  [    间距    ]  C
//       1份            2份

注意事项

Expanded 不能单独使用

Expanded 必须在 RowColumnFlex 中使用,否则会报错:

dart
// ❌ 错误:Expanded 在 Container 中
Container(
  child: Expanded(child: Text('错误')),
)

// ✅ 正确:Expanded 在 Row 中
Row(
  children: [
    Expanded(child: Text('正确')),
  ],
)

不要在 ScrollView 中直接使用 Expanded

dart
// ❌ 错误:SingleChildScrollView 中的 Expanded 没有意义
SingleChildScrollView(
  child: Column(
    children: [
      Expanded(child: ...),  // 父组件不提供有界约束
    ],
  ),
)

基于 Flutter 官方文档整理