Flutter Flexible

在 Flutter 中,Flexible 是一个重要的布局组件,用于在 RowColumnFlex 中创建灵活的布局。让我详细解释它的用法:

基本概念

Flexible 可以让子组件在主轴方向上灵活伸缩 ,与其他 FlexibleExpanded 组件共享可用空间。

主要属性

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: () {},
          ),
        ],
      ),
    ),
  ],
)

注意事项

  1. 父容器需要有限制Flexible 的父组件(Row/Column/Flex)必须有有限的主轴尺寸

  2. 正确使用 fit

    dart

    复制代码
    // ❌ 可能不会按预期工作
    Flexible(
      fit: FlexFit.loose,
      child: Container(), // 空容器,可能不显示
    )
    
    // ✅ 明确指定尺寸或使用 tight
    Flexible(
      fit: FlexFit.tight,
      child: Container(color: Colors.red),
    )
  3. 与 SizedBox.expand 结合

    dart

    复制代码
    Flexible(
      child: SizedBox.expand(  // 强制填满父容器
        child: Container(color: Colors.red),
      ),
    )
  4. 性能考虑 :过度使用 Flexible 可能影响性能,特别是在列表中使用时

最佳实践

dart

复制代码
// 推荐:使用 Expanded 当需要填满空间时
Row(
  children: [
    Expanded(child: Content()),  // 更简洁
  ],
)

// 推荐:使用 Flexible 当需要 loose 模式时
Row(
  children: [
    Flexible(
      fit: FlexFit.loose,
      child: Container(width: 100), // 保持原有宽度
    ),
  ],
)

Flexible 是 Flutter 响应式布局的核心组件之一,合理使用可以让你的界面在不同屏幕尺寸上都能良好适配。

相关推荐
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台2 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone2 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc2 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo2 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077002 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
茶底世界之下2 天前
为什么预览、录制、离线导出不能共享同一个背压策略?
ios·swift
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen2 天前
属性动画原理与高级动画实现
android·kotlin·canvas