基础入门 Flutter for OpenHarmony:Flexible 弹性布局组件详解

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
🎯 欢迎来到 Flutter for OpenHarmony 社区!本文将深入讲解 Flutter 中 Flexible 弹性布局组件的使用方法,带你从基础到精通,掌握这一核心布局组件。


一、Flexible 组件概述

在响应式布局设计中,弹性布局是一种非常重要的布局方式。通过弹性布局,子组件可以根据父容器的可用空间自动调整大小,实现不同屏幕尺寸的适配。Flutter 提供了 Flexible 组件,让开发者能够轻松创建弹性布局效果。

📋 Flexible 组件特点

特点 说明
弹性空间分配 子组件可以按比例分配剩余空间
灵活的适配模式 支持 loose、tight 等多种适配模式
与 Expanded 的关系 Expanded 是 Flexible 的一个特例
方向支持 可在 Row 和 Column 中使用

什么是弹性布局?

弹性布局是一种响应式布局方式,具有以下特点:

  1. 自动调整大小:子组件根据可用空间自动调整
  2. 比例分配:可以按比例分配剩余空间
  3. 灵活适配:适配不同屏幕尺寸和方向
  4. 嵌套支持:可以多层嵌套实现复杂布局

Flexible 与 Expanded 的区别

Flexible 和 Expanded 都用于弹性布局,但它们有重要区别:

特性 Flexible Expanded
空间分配 可以小于可用空间 必须填满可用空间
子组件大小 可以保持原始大小 强制填满分配空间
fit 参数 支持 loose 和 tight 固定为 tight
使用场景 需要灵活调整大小 需要填满剩余空间

简单来说:

  • Expanded:强制子组件填满分配的空间
  • Flexible:允许子组件根据内容大小灵活调整

💡 使用场景:Flexible 适合需要子组件保持原始大小或灵活调整的场景,Expanded 适合需要子组件填满剩余空间的场景。


二、Flexible 基础用法

Flexible 的使用非常简单,只需要将其包裹在子组件外面,并设置相应的参数。让我们从最基础的用法开始学习。

2.1 最简单的 Flexible

最基础的 Flexible 只需要提供 child 子组件:

dart 复制代码
Row(
  children: [
    Flexible(
      child: Container(
        color: Colors.red,
        height: 100,
      ),
    ),
    Flexible(
      child: Container(
        color: Colors.green,
        height: 100,
      ),
    ),
    Flexible(
      child: Container(
        color: Colors.blue,
        height: 100,
      ),
    ),
  ],
)

代码解析:

  • 三个 Flexible 子组件会平均分配 Row 的可用空间
  • 每个子组件各占 1/3 的宽度
  • 默认情况下,flex 值为 1

2.2 flex 参数详解

flex 参数用于控制子组件分配空间的比例:

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),
    ),
  ],
)

flex 参数说明:

flex 值 分配比例 说明
flex: 1 1/4 占总空间的 25%
flex: 2 2/4 占总空间的 50%
flex: 1 1/4 占总空间的 25%

2.3 fit 参数详解

fit 参数控制子组件如何适配分配的空间:

dart 复制代码
// loose 模式:子组件可以小于分配空间
Flexible(
  fit: FlexFit.loose,
  child: Container(width: 50, color: Colors.red),
)

// tight 模式:子组件必须填满分配空间
Flexible(
  fit: FlexFit.tight,
  child: Container(color: Colors.green),
)

FlexFit 值说明:

效果 说明
FlexFit.loose 宽松适配 子组件可以小于分配的空间
FlexFit.tight 紧凑适配 子组件必须填满分配的空间

2.4 完整示例

下面是一个完整的可运行示例,展示了 Flexible 的基础用法:

dart 复制代码
class FlexibleBasicExample extends StatelessWidget {
  const FlexibleBasicExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flexible 基础示例')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            const Text('平均分配空间:'),
            const SizedBox(height: 8),
            SizedBox(
              height: 60,
              child: Row(
                children: [
                  Flexible(
                    child: Container(
                      color: Colors.red[300],
                      child: const Center(child: Text('1:1:1')),
                    ),
                  ),
                  Flexible(
                    child: Container(
                      color: Colors.green[300],
                      child: const Center(child: Text('1:1:1')),
                    ),
                  ),
                  Flexible(
                    child: Container(
                      color: Colors.blue[300],
                      child: const Center(child: Text('1:1:1')),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),
            const Text('按比例分配空间:'),
            const SizedBox(height: 8),
            SizedBox(
              height: 60,
              child: Row(
                children: [
                  Flexible(
                    flex: 1,
                    child: Container(
                      color: Colors.red[300],
                      child: const Center(child: Text('flex:1')),
                    ),
                  ),
                  Flexible(
                    flex: 2,
                    child: Container(
                      color: Colors.green[300],
                      child: const Center(child: Text('flex:2')),
                    ),
                  ),
                  Flexible(
                    flex: 3,
                    child: Container(
                      color: Colors.blue[300],
                      child: const Center(child: Text('flex:3')),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

三、Flexible 与 Expanded 的对比

Flexible 和 Expanded 是 Flutter 中两个重要的弹性布局组件,理解它们的区别对于正确使用非常重要。

3.1 等价关系

以下两种写法是等价的:

dart 复制代码
// 使用 Expanded
Expanded(
  child: Container(...),
)

// 使用 Flexible + tight
Flexible(
  fit: FlexFit.tight,
  child: Container(...),
)

3.2 实际对比示例

dart 复制代码
Row(
  children: [
    // Flexible - 子组件保持原始大小
    Flexible(
      fit: FlexFit.loose,
      child: Container(
        width: 50,  // 保持 50 宽度
        color: Colors.red,
        child: const Text('Flexible'),
      ),
    ),
    // Expanded - 子组件填满分配空间
    Expanded(
      child: Container(
        color: Colors.green,
        child: const Text('Expanded'),
      ),
    ),
  ],
)

对比说明:

组件 行为 效果
Flexible (loose) 保持原始大小 子组件宽度为 50
Expanded 填满剩余空间 子组件填满所有剩余空间

3.3 选择建议

使用 Flexible 的场景:

  • 子组件需要保持原始大小
  • 子组件大小可能根据内容变化
  • 需要更精细的空间控制

使用 Expanded 的场景:

  • 子组件需要填满剩余空间
  • 创建等宽或等高的布局
  • 简单的空间分配需求

四、flex 比例详解

flex 参数是 Flexible 的核心,理解 flex 的工作原理对于创建复杂布局非常重要。

4.1 相同比例分配

当所有子组件的 flex 值相同时,它们会平均分配空间:

dart 复制代码
Row(
  children: [
    Flexible(flex: 1, child: Container(color: Colors.red)),
    Flexible(flex: 1, child: Container(color: Colors.green)),
    Flexible(flex: 1, child: Container(color: Colors.blue)),
  ],
)

每个子组件各占 1/3 的空间。

4.2 不同比例分配

不同的 flex 值会按比例分配空间:

dart 复制代码
Row(
  children: [
    Flexible(flex: 1, child: Container(color: Colors.red)),    // 1/6
    Flexible(flex: 2, child: Container(color: Colors.green)),  // 2/6
    Flexible(flex: 3, child: Container(color: Colors.blue)),   // 3/6
  ],
)

4.3 与固定大小组件混合

Flexible 可以与固定大小的组件混合使用:

dart 复制代码
Row(
  children: [
    Container(width: 100, color: Colors.grey),      // 固定宽度
    Flexible(flex: 1, child: Container(color: Colors.green)),  // 弹性
    Container(width: 100, color: Colors.grey),     // 固定宽度
  ],
)

计算规则:

  1. 先计算固定大小组件占用的空间
  2. 剩余空间按 flex 比例分配给 Flexible 组件

五、Column 中的 Flexible

Flexible 在 Column 中的用法与 Row 类似,只是方向变为垂直。

5.1 垂直布局

dart 复制代码
Column(
  children: [
    Flexible(
      flex: 1,
      child: Container(color: Colors.red),
    ),
    Flexible(
      flex: 2,
      child: Container(color: Colors.green),
    ),
    Flexible(
      flex: 1,
      child: Container(color: Colors.blue),
    ),
  ],
)

5.2 固定头部和底部

这是一个常见的布局模式,头部和底部固定高度,中间内容自适应:

dart 复制代码
Column(
  children: [
    Container(
      height: 60,
      color: Colors.blue,
      child: const Center(child: Text('头部')),
    ),
    Expanded(
      child: Container(
        color: Colors.grey[100],
        child: const Center(child: Text('内容区域')),
      ),
    ),
    Container(
      height: 60,
      color: Colors.green,
      child: const Center(child: Text('底部')),
    ),
  ],
)

六、Flexible 实际应用场景

Flexible 在实际开发中有着广泛的应用,让我们通过具体示例来学习。

6.1 三栏布局

dart 复制代码
class ThreeColumnLayout extends StatelessWidget {
  const ThreeColumnLayout({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('三栏布局')),
      body: Row(
        children: [
          Flexible(
            flex: 1,
            child: Container(
              color: Colors.blue[100],
              child: ListView(
                children: List.generate(
                  10,
                  (i) => ListTile(title: Text('左侧 $i')),
                ),
              ),
            ),
          ),
          Flexible(
            flex: 2,
            child: Container(
              color: Colors.grey[100],
              child: const Center(child: Text('主内容区')),
            ),
          ),
          Flexible(
            flex: 1,
            child: Container(
              color: Colors.green[100],
              child: ListView(
                children: List.generate(
                  10,
                  (i) => ListTile(title: Text('右侧 $i')),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

6.2 表单布局

dart 复制代码
class FormLayout extends StatelessWidget {
  const FormLayout({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('表单布局')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Row(
              children: [
                const SizedBox(width: 80, child: Text('用户名:')),
                Expanded(
                  child: TextField(
                    decoration: const InputDecoration(
                      hintText: '请输入用户名',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 16),
            Row(
              children: [
                const SizedBox(width: 80, child: Text('密码:')),
                Expanded(
                  child: TextField(
                    obscureText: true,
                    decoration: const InputDecoration(
                      hintText: '请输入密码',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

6.3 底部按钮栏

dart 复制代码
class BottomButtonBar extends StatelessWidget {
  const BottomButtonBar({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('底部按钮栏')),
      body: Column(
        children: [
          const Expanded(
            child: Center(child: Text('内容区域')),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                Expanded(
                  child: OutlinedButton(
                    onPressed: () {},
                    child: const Text('取消'),
                  ),
                ),
                const SizedBox(width: 16),
                Expanded(
                  child: ElevatedButton(
                    onPressed: () {},
                    child: const Text('确定'),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

6.4 响应式卡片

dart 复制代码
class ResponsiveCard extends StatelessWidget {
  const ResponsiveCard({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('响应式卡片')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: LayoutBuilder(
          builder: (context, constraints) {
            final isWide = constraints.maxWidth > 600;
            return Flex(
              direction: isWide ? Axis.horizontal : Axis.vertical,
              children: [
                Flexible(
                  flex: isWide ? 1 : 0,
                  child: Container(
                    height: isWide ? null : 150,
                    color: Colors.blue[100],
                    child: const Center(child: Text('图片区域')),
                  ),
                ),
                Flexible(
                  flex: isWide ? 2 : 1,
                  child: const Padding(
                    padding: EdgeInsets.all(16),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '标题',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        SizedBox(height: 8),
                        Text('这是卡片的描述内容,展示了响应式布局的效果。'),
                      ],
                    ),
                  ),
                ),
              ],
            );
          },
        ),
      ),
    );
  }
}

6.5 标签栏

dart 复制代码
class TabBarExample extends StatelessWidget {
  const TabBarExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('标签栏')),
      body: Column(
        children: [
          Container(
            height: 48,
            color: Colors.grey[200],
            child: Row(
              children: [
                Expanded(
                  child: TextButton(
                    onPressed: () {},
                    child: const Text('首页'),
                  ),
                ),
                Expanded(
                  child: TextButton(
                    onPressed: () {},
                    child: const Text('分类'),
                  ),
                ),
                Expanded(
                  child: TextButton(
                    onPressed: () {},
                    child: const Text('购物车'),
                  ),
                ),
                Expanded(
                  child: TextButton(
                    onPressed: () {},
                    child: const Text('我的'),
                  ),
                ),
              ],
            ),
          ),
          const Expanded(
            child: Center(child: Text('内容区域')),
          ),
        ],
      ),
    );
  }
}

七、嵌套使用

Flexible 可以嵌套使用,实现复杂的布局效果。

7.1 嵌套示例

dart 复制代码
Column(
  children: [
    Flexible(
      flex: 1,
      child: Row(
        children: [
          Flexible(
            flex: 1,
            child: Container(color: Colors.red),
          ),
          Flexible(
            flex: 1,
            child: Container(color: Colors.green),
          ),
        ],
      ),
    ),
    Flexible(
      flex: 1,
      child: Row(
        children: [
          Flexible(
            flex: 2,
            child: Container(color: Colors.blue),
          ),
          Flexible(
            flex: 1,
            child: Container(color: Colors.yellow),
          ),
        ],
      ),
    ),
  ],
)

7.2 复杂布局示例

dart 复制代码
class ComplexLayout extends StatelessWidget {
  const ComplexLayout({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Container(
            height: 56,
            color: Colors.blue,
            child: const Center(child: Text('AppBar')),
          ),
          Expanded(
            child: Row(
              children: [
                Container(
                  width: 200,
                  color: Colors.grey[200],
                  child: const Center(child: Text('侧边栏')),
                ),
                Expanded(
                  child: Column(
                    children: [
                      Expanded(
                        child: Container(
                          color: Colors.white,
                          child: const Center(child: Text('主内容区')),
                        ),
                      ),
                      Container(
                        height: 60,
                        color: Colors.grey[100],
                        child: const Center(child: Text('底部栏')),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

八、性能考虑

Flexible 组件虽然功能强大,但在某些情况下需要注意性能优化。

8.1 性能优化建议

  1. 避免过度嵌套:过多的嵌套会增加布局计算复杂度
  2. 合理使用 flex:简单的比例分配比复杂的计算更高效
  3. 使用 const 构造函数:对于静态子组件,使用 const 可以提高性能
  4. 避免频繁重建:如果布局需要频繁变化,考虑使用 AnimatedSize

8.2 何时使用 Flexible

推荐使用:

  • 需要响应式布局
  • 需要按比例分配空间
  • 需要创建自适应界面

不推荐使用:

  • 固定大小的布局(使用 SizedBox)
  • 简单的居中布局(使用 Center)
  • 绝对定位布局(使用 Stack + Positioned)

九、完整代码示例

下面是一个完整的、可以直接运行的 main.dart 文件,展示了 Flexible 组件的各种用法:

dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flexible 组件示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const FlexibleDemoPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flexible 弹性布局组件详解'),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildSection('一、平均分配', [
              const Text('三个 Flexible 子组件平均分配空间:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 60,
                child: Row(
                  children: [
                    Flexible(
                      child: Container(
                        color: Colors.red[300],
                        child: const Center(child: Text('1:1')),
                      ),
                    ),
                    Flexible(
                      child: Container(
                        color: Colors.green[300],
                        child: const Center(child: Text('1:1')),
                      ),
                    ),
                    Flexible(
                      child: Container(
                        color: Colors.blue[300],
                        child: const Center(child: Text('1:1')),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('二、比例分配', [
              const Text('使用 flex 参数按比例分配空间:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 60,
                child: Row(
                  children: [
                    Flexible(
                      flex: 1,
                      child: Container(
                        color: Colors.red[300],
                        child: const Center(child: Text('flex: 1')),
                      ),
                    ),
                    Flexible(
                      flex: 2,
                      child: Container(
                        color: Colors.green[300],
                        child: const Center(child: Text('flex: 2')),
                      ),
                    ),
                    Flexible(
                      flex: 3,
                      child: Container(
                        color: Colors.blue[300],
                        child: const Center(child: Text('flex: 3')),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('三、Flexible vs Expanded', [
              const Text('Flexible 可以保持原始大小,Expanded 必须填满:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 60,
                child: Row(
                  children: [
                    Flexible(
                      fit: FlexFit.loose,
                      child: Container(
                        width: 80,
                        color: Colors.orange[300],
                        child: const Center(child: Text('Flexible\n(loose)')),
                      ),
                    ),
                    Expanded(
                      child: Container(
                        color: Colors.purple[300],
                        child: const Center(child: Text('Expanded')),
                      ),
                    ),
                    Flexible(
                      fit: FlexFit.tight,
                      child: Container(
                        color: Colors.teal[300],
                        child: const Center(child: Text('Flexible\n(tight)')),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('四、与固定大小混合', [
              const Text('Flexible 与固定大小组件混合使用:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 60,
                child: Row(
                  children: [
                    Container(
                      width: 60,
                      color: Colors.grey[400],
                      child: const Center(child: Text('固定')),
                    ),
                    Flexible(
                      flex: 1,
                      child: Container(
                        color: Colors.red[300],
                        child: const Center(child: Text('flex: 1')),
                      ),
                    ),
                    Container(
                      width: 80,
                      color: Colors.grey[400],
                      child: const Center(child: Text('固定')),
                    ),
                    Flexible(
                      flex: 2,
                      child: Container(
                        color: Colors.green[300],
                        child: const Center(child: Text('flex: 2')),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('五、Column 垂直布局', [
              const Text('在 Column 中使用 Flexible:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 200,
                child: Column(
                  children: [
                    Flexible(
                      flex: 1,
                      child: Container(
                        width: double.infinity,
                        color: Colors.red[300],
                        child: const Center(child: Text('flex: 1')),
                      ),
                    ),
                    Flexible(
                      flex: 2,
                      child: Container(
                        width: double.infinity,
                        color: Colors.green[300],
                        child: const Center(child: Text('flex: 2')),
                      ),
                    ),
                    Flexible(
                      flex: 1,
                      child: Container(
                        width: double.infinity,
                        color: Colors.blue[300],
                        child: const Center(child: Text('flex: 1')),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('六、固定头部底部', [
              const Text('头部和底部固定,中间内容自适应:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 200,
                child: Column(
                  children: [
                    Container(
                      height: 40,
                      color: Colors.blue[400],
                      child: const Center(
                        child: Text('头部', style: TextStyle(color: Colors.white)),
                      ),
                    ),
                    Expanded(
                      child: Container(
                        width: double.infinity,
                        color: Colors.grey[100],
                        child: const Center(child: Text('内容区域(Expanded)')),
                      ),
                    ),
                    Container(
                      height: 40,
                      color: Colors.green[400],
                      child: const Center(
                        child: Text('底部', style: TextStyle(color: Colors.white)),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('七、表单布局', [
              const Text('标签固定宽度,输入框自适应:'),
              const SizedBox(height: 12),
              Container(
                padding: const EdgeInsets.all(16),
                decoration: BoxDecoration(
                  color: Colors.grey[50],
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Column(
                  children: [
                    Row(
                      children: [
                        const SizedBox(width: 80, child: Text('用户名:')),
                        Expanded(
                          child: TextField(
                            decoration: InputDecoration(
                              hintText: '请输入用户名',
                              border: const OutlineInputBorder(),
                              contentPadding: const EdgeInsets.symmetric(
                                horizontal: 12,
                                vertical: 8,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 12),
                    Row(
                      children: [
                        const SizedBox(width: 80, child: Text('密码:')),
                        Expanded(
                          child: TextField(
                            obscureText: true,
                            decoration: InputDecoration(
                              hintText: '请输入密码',
                              border: const OutlineInputBorder(),
                              contentPadding: const EdgeInsets.symmetric(
                                horizontal: 12,
                                vertical: 8,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('八、底部按钮栏', [
              const Text('两个按钮平均分配宽度:'),
              const SizedBox(height: 12),
              Row(
                children: [
                  Expanded(
                    child: OutlinedButton(
                      onPressed: () {},
                      child: const Text('取消'),
                    ),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: ElevatedButton(
                      onPressed: () {},
                      child: const Text('确定'),
                    ),
                  ),
                ],
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('九、嵌套布局', [
              const Text('Flexible 嵌套使用:'),
              const SizedBox(height: 12),
              SizedBox(
                height: 200,
                child: Column(
                  children: [
                    Flexible(
                      flex: 1,
                      child: Row(
                        children: [
                          Flexible(
                            flex: 1,
                            child: Container(color: Colors.red[300]),
                          ),
                          Flexible(
                            flex: 1,
                            child: Container(color: Colors.green[300]),
                          ),
                        ],
                      ),
                    ),
                    Flexible(
                      flex: 1,
                      child: Row(
                        children: [
                          Flexible(
                            flex: 2,
                            child: Container(color: Colors.blue[300]),
                          ),
                          Flexible(
                            flex: 1,
                            child: Container(color: Colors.yellow[300]),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 24),
            _buildSection('十、标签栏', [
              const Text('等宽标签按钮:'),
              const SizedBox(height: 12),
              Container(
                height: 48,
                decoration: BoxDecoration(
                  color: Colors.grey[200],
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Row(
                  children: [
                    Expanded(
                      child: TextButton(
                        onPressed: () {},
                        child: const Text('首页'),
                      ),
                    ),
                    Expanded(
                      child: TextButton(
                        onPressed: () {},
                        child: const Text('分类'),
                      ),
                    ),
                    Expanded(
                      child: TextButton(
                        onPressed: () {},
                        child: const Text('购物车'),
                      ),
                    ),
                    Expanded(
                      child: TextButton(
                        onPressed: () {},
                        child: const Text('我的'),
                      ),
                    ),
                  ],
                ),
              ),
            ]),
            const SizedBox(height: 32),
          ],
        ),
      ),
    );
  }

  Widget _buildSection(String title, List<Widget> children) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 8),
        ...children,
      ],
    );
  }
}

十、总结

Flexible 是 Flutter 中一个核心的布局组件,通过本文的学习,我们掌握了以下内容:

📝 知识点回顾

  1. Flexible 基础:了解 Flexible 的基本用法和参数
  2. flex 参数:掌握按比例分配空间的方法
  3. fit 参数:理解 loose 和 tight 两种适配模式
  4. 与 Expanded 的对比:区分两种弹性布局组件的使用场景
  5. 实际应用场景:三栏布局、表单布局、底部按钮栏等
  6. 嵌套使用:实现复杂的布局效果

🎯 最佳实践

  1. 根据需求选择 Flexible 或 Expanded
  2. 合理设置 flex 比例值
  3. 避免过度嵌套影响性能
  4. 使用 LayoutBuilder 实现响应式布局

🔗 延伸阅读

相关推荐
阿林来了2 小时前
Flutter三方库适配OpenHarmony【flutter_speech】— FlutterPlugin 接口适配
flutter·harmonyos
空白诗2 小时前
基础入门 Flutter for OpenHarmony:IndexedStack 索引堆叠组件详解
flutter
阿林来了2 小时前
Flutter三方库适配OpenHarmony【flutter_speech】— Core Speech Kit 概述
flutter·harmonyos
松叶似针2 小时前
Flutter三方库适配OpenHarmony【secure_application】— Window 管理与 getLastWindow API
flutter·harmonyos
空白诗3 小时前
基础入门 Flutter for OpenHarmony:Transform 变换组件详解
flutter
空白诗3 小时前
基础入门 Flutter for OpenHarmony:DecoratedBox 装饰盒子组件详解
flutter
键盘鼓手苏苏3 小时前
Flutter for OpenHarmony:random_string 简单灵活的随机字符串生成器(验证码、密钥、UUID) 深度解析与鸿蒙适配指南
开发语言·flutter·华为·rust·harmonyos
无巧不成书021811 小时前
【开源鸿蒙+Flutter实战】Step Two复盘(DAY8-14)|复杂页面落地·多终端适配·状态保持实战指南
flutter·开源·harmonyos
sdff1139612 小时前
【HarmonyOS】鸿蒙Flutter跨设备流转技术实战指南
flutter·wpf·harmonyos