在 Flutter 中,Flexible 是一个重要的布局组件,用于在 Row、Column 或 Flex 中创建灵活的布局。让我详细解释它的用法:
基本概念
Flexible 可以让子组件在主轴方向上灵活伸缩 ,与其他 Flexible 或 Expanded 组件共享可用空间。
主要属性
1. flex(弹性系数)
dart
Flexible(
flex: 2, // 权重,默认值为1
child: Container(color: Colors.red),
)
2. fit(填充方式)
dart
Flexible(
fit: FlexFit.tight, // 强制填满分配的空间
child: Container(color: Colors.blue),
)
Flexible(
fit: FlexFit.loose, // 可以小于分配的空间(默认值)
child: Container(width: 50), // 只占用50宽度
)
与 Expanded 的区别
dart
// Expanded 实际上是 Flexible 的快捷方式:
Expanded = Flexible(fit: FlexFit.tight)
// 区别:
// - Expanded: 必须填满分配的空间
// - Flexible: 可以填满,也可以不填满(取决于 fit 参数)
实用示例
示例1:基本使用
dart
Row(
children: [
Flexible(
flex: 1,
child: Container(color: Colors.red, height: 100),
),
Flexible(
flex: 2,
child: Container(color: Colors.green, height: 100),
),
Flexible(
flex: 1,
child: Container(color: Colors.blue, height: 100),
),
],
)
// 比例:红:绿:蓝 = 1:2:1
示例2:响应式布局
dart
Row(
children: [
// 固定宽度部分
Container(
width: 80,
color: Colors.grey,
child: Icon(Icons.menu),
),
// 自适应部分
Flexible(
child: Container(
color: Colors.blue,
child: TextField(
decoration: InputDecoration(hintText: '搜索...'),
),
),
),
// 另一个固定部分
Container(
width: 60,
color: Colors.grey,
child: Icon(Icons.search),
),
],
)
示例3:Column 中的使用
dart
Column(
children: [
Container(
height: 100,
color: Colors.red,
child: Center(child: Text('固定高度')),
),
Flexible( // 占据剩余空间
child: Container(
color: Colors.green,
child: ListView(
children: [
ListTile(title: Text('项目1')),
ListTile(title: Text('项目2')),
// ...更多列表项
],
),
),
),
Container(
height: 60,
color: Colors.blue,
child: Center(child: Text('底部栏')),
),
],
)
示例4:嵌套 Flexible
dart
Column(
children: [
Flexible(
flex: 2,
child: Row(
children: [
Flexible(
flex: 1,
child: Container(color: Colors.red),
),
Flexible(
flex: 3,
child: Container(color: Colors.green),
),
],
),
),
Flexible(
flex: 1,
child: Container(color: Colors.blue),
),
],
)
常见使用场景
场景1:三栏布局
dart
Row(
children: [
Flexible(flex: 1, child: Sidebar()),
Flexible(flex: 3, child: MainContent()),
Flexible(flex: 1, child: RightPanel()),
],
)
场景2:带图标的输入框
dart
Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Icon(Icons.search),
SizedBox(width: 8),
Flexible( // 输入框自适应
child: TextField(
decoration: InputDecoration(
hintText: '请输入内容',
border: InputBorder.none,
),
),
),
Icon(Icons.mic),
],
),
)
场景3:聊天界面
dart
Column(
children: [
Flexible( // 消息列表自适应
child: ListView.builder(
itemCount: messages.length,
itemBuilder: (context, index) => MessageItem(messages[index]),
),
),
Container( // 固定高度的输入框
padding: EdgeInsets.all(8),
child: Row(
children: [
Flexible(
child: TextField(
decoration: InputDecoration(
hintText: '输入消息...',
border: OutlineInputBorder(),
),
),
),
IconButton(
icon: Icon(Icons.send),
onPressed: () {},
),
],
),
),
],
)
注意事项
-
父容器需要有限制 :
Flexible的父组件(Row/Column/Flex)必须有有限的主轴尺寸 -
正确使用 fit:
dart
// ❌ 可能不会按预期工作 Flexible( fit: FlexFit.loose, child: Container(), // 空容器,可能不显示 ) // ✅ 明确指定尺寸或使用 tight Flexible( fit: FlexFit.tight, child: Container(color: Colors.red), ) -
与 SizedBox.expand 结合:
dart
Flexible( child: SizedBox.expand( // 强制填满父容器 child: Container(color: Colors.red), ), ) -
性能考虑 :过度使用
Flexible可能影响性能,特别是在列表中使用时
最佳实践
dart
// 推荐:使用 Expanded 当需要填满空间时
Row(
children: [
Expanded(child: Content()), // 更简洁
],
)
// 推荐:使用 Flexible 当需要 loose 模式时
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(width: 100), // 保持原有宽度
),
],
)
Flexible 是 Flutter 响应式布局的核心组件之一,合理使用可以让你的界面在不同屏幕尺寸上都能良好适配。