Expanded / Flexible
Expanded 和 Flexible 用于在 Row 或 Column 中让子组件按比例分配剩余空间。
Expanded
构造函数
dart
Expanded({
Key? key, // 组件标识
int flex = 1, // 弹性系数(按比例分配空间的权重)
required Widget child, // 子组件(必填)
})属性速查
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
flex | int | 1 | 弹性系数,多个 Expanded 时按此比例分配剩余空间 |
child | Widget | 必填 | 子组件 |
快速示例
占满剩余空间
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
Flexible 比 Expanded 更灵活,可以控制子组件是「占满」还是「包裹」。
构造函数
dart
Flexible({
Key? key, // 组件标识
int flex = 1, // 弹性系数(按比例分配空间的权重)
FlexFit fit = FlexFit.loose, // 填充模式:loose=可小于分配空间,tight=必须填满
required Widget child, // 子组件(必填)
})属性速查
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
flex | int | 1 | 弹性系数,多个 Flexible 时按此比例分配剩余空间 |
fit | FlexFit | loose | 填充模式 |
child | Widget | 必填 | 子组件 |
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 速查
| 特性 | Expanded | Flexible | Spacer |
|---|---|---|---|
| 本质 | 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 必须在 Row、Column 或 Flex 中使用,否则会报错:
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: ...), // 父组件不提供有界约束
],
),
)