Flutter 系列教程:布局基础 (上) - `Container`, `Row`, `Column`, `Flex`

欢迎来到 Flutter 布局的世界!如果说 Widget 是乐高积木,那么布局 Widget 就是你用来搭建城堡的说明书和骨架。学会了布局,你就能将独立的组件组合成任何你想要的复杂界面。

今天,我们将聚焦于线性布局,即沿着水平或垂直方向排列组件。

学习目标

  • 掌握 Container Widget,学会如何用它来装饰和约束单个子组件。
  • 理解 Row (水平) 和 Column (垂直) 的主轴 (Main Axis) 与交叉轴 (Cross Axis) 的概念。
  • 学会使用 mainAxisAlignmentcrossAxisAlignment 来控制子组件的对齐方式。
  • 了解 Flex,以及它与 RowColumn 的关系。

1. Container:万能的容器

你可以将 Container 想象成网页开发中的 <div> 标签,它是一个功能极其强大的"盒子"。它既可以包裹一个子组件 (child),也可以通过自身的属性来定义尺寸、边距、背景色、边框等装饰效果。

核心属性

  • child: 容器内包裹的子组件。
  • width, height: 明确指定容器的宽度和高度。
  • color: 容器的背景颜色。
  • padding: 内边距 ,即 child 相对于容器边界的距离。
  • margin: 外边距,即容器相对于其父组件的距离。
  • decoration (BoxDecoration ): 强大的装饰属性,用于设置边框 (border)、圆角 (borderRadius)、阴影 (boxShadow)、渐变 (gradient)等。注意:如果同时设置了 colordecorationcolor 属性必须定义在 decoration 内部,否则会报错。

代码示例:创建一个带样式的卡片

less 复制代码
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(
      home: Scaffold(
        backgroundColor: Colors.grey, // 设置一个灰色背景,以凸显 margin
        appBar: AppBar(title: const Text('Container Demo')),
        body: Center(
          child: Container(
            // 如果设置了 decoration,color 必须放在 decoration 里面
            decoration: BoxDecoration(
              color: Colors.white,
              border: Border.all(
                color: Colors.blue,
                width: 2.0,
              ),
              borderRadius: BorderRadius.circular(12.0),
              boxShadow: [
                BoxShadow(
                  color: Colors.black.withOpacity(0.2),
                  spreadRadius: 3,
                  blurRadius: 7,
                  offset: const Offset(0, 3), // changes position of shadow
                ),
              ],
            ),
            width: 250,
            height: 150,
            padding: const EdgeInsets.all(20.0), // 内边距
            margin: const EdgeInsets.all(30.0),  // 外边距
            child: const Text(
              '这是一个漂亮的 Container!',
              style: TextStyle(fontSize: 20),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }
}

2. Row & Column:线性布局的核心

RowColumn 是 Flutter 中最常用的布局组件,它们允许你将一组子组件 (children) 沿水平或垂直方向进行排列。

  • Row : 将其 children 沿水平方向排列。
  • Column : 将其 children 沿垂直方向排列。

核心概念:主轴 (Main Axis) 与 交叉轴 (Cross Axis)

这是理解 RowColumn 的关键!

  • 对于 Row

    • 主轴 (Main Axis)水平方向 (从左到右)。
    • 交叉轴 (Cross Axis)垂直方向 (从上到下)。
  • 对于 Column

    • 主轴 (Main Axis)垂直方向 (从上到下)。
    • 交叉轴 (Cross Axis)水平方向 (从左到右)。

核心属性

  • children: 一个 Widget 列表,是需要被排列的子组件。
  • mainAxisAlignment: 控制子组件在主轴 上的对齐方式。
    • MainAxisAlignment.start: 靠前对齐 (默认值)。
    • MainAxisAlignment.end: 靠后对齐。
    • MainAxisAlignment.center: 居中对齐。
    • MainAxisAlignment.spaceBetween: 两端对齐,子组件之间的间隔相等
    • MainAxisAlignment.spaceAround: 每个子组件左右两侧的间隔相等,所以首尾两个组件到边界的距离是组件之间间隔的一半。
    • MainAxisAlignment.spaceEvenly: 所有子组件之间 以及首尾到边界的间隔完全相等。
  • crossAxisAlignment: 控制子组件在交叉轴 上的对齐方式。
    • CrossAxisAlignment.start: 靠前对齐。
    • CrossAxisAlignment.end: 靠后对齐。
    • CrossAxisAlignment.center: 居中对齐 (默认值)。
    • CrossAxisAlignment.stretch: 拉伸子组件,使其填满交叉轴空间。

代码示例:RowColumn 的对齐演示

less 复制代码
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(
      home: Scaffold(
        appBar: AppBar(title: const Text('Row & Column Demo')),
        body: Column(
          children: [
            // --- Row 示例 ---
            Container(
              height: 100, // 给 Row 一个高度以观察 CrossAxisAlignment
              color: Colors.yellow,
              child: const Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly, 
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Icon(Icons.star, size: 50),
                  Icon(Icons.star, size: 50),
                  Icon(Icons.star, size: 50),
                ],
              ),
            ),
            
            const Divider(), // 添加一个分割线

            // --- Column 示例 ---
            Container(
              width: 200, // 给 Column 一个宽度以观察 CrossAxisAlignment
              color: Colors.blue,
              child: const Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.stretch, // 拉伸填满宽度
                children: <Widget>[
                  Text('Item 1', textAlign: TextAlign.center, style: TextStyle(fontSize: 24)),
                  Text('Item 2', textAlign: TextAlign.center, style: TextStyle(fontSize: 24)),
                  Text('Item 3', textAlign: TextAlign.center, style: TextStyle(fontSize: 24)),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

动手试试 :将上面代码中的 mainAxisAlignmentcrossAxisAlignment 的值修改为其他枚举值,然后热重载,亲眼看看布局发生了什么变化!这是最好的学习方式。


3. FlexRowColumn 的"父类"

你可能不知道,RowColumn 其实都是 Flex Widget 的"语法糖"。Flex 是一个更底层的组件,它通过一个 direction 属性来决定其子组件的排列方向。

  • Row 等价于 Flex(direction: Axis.horizontal)
  • Column 等价于 Flex(direction: Axis.vertical)

那我们为什么不直接用 Flex 呢? 因为 RowColumn 的代码可读性更高,意图更明确。在绝大多数情况下,你都应该优先使用 RowColumn。只有当你需要动态地 根据某个条件来决定布局是水平还是垂直时,Flex 才会派上用场。

dart 复制代码
// 这是一个 Row
Row(children: <Widget>[...]);

// 它完全等价于
Flex(
  direction: Axis.horizontal,
  children: <Widget>[...],
);

总结

今天我们学习了 Flutter 布局的四大金刚:

  • Container: 用于包裹、装饰和约束单个 Widget 的瑞士军刀。
  • Row: 用于将子组件水平排列。
  • Column: 用于将子组件垂直排列。
  • 主轴/交叉轴 : 是理解 RowColumn 对齐方式的钥匙。
  • Flex : 是 RowColumn 的底层实现,用于更动态的布局场景。

掌握了这些,你就已经具备了搭建 80% 静态页面的能力。在下一篇教程中,我们将学习如何处理重叠布局 (Stack) 和弹性布局 (Expanded),让你的布局能力再上一个台阶!我们下篇见!

相关推荐
西西学代码18 分钟前
Flutter---GridView+自定义控件
flutter
peachSoda738 分钟前
封装一个不同跳转方式的通用方法(跳转外部链接,跳转其他小程序,跳转半屏小程序)
前端·javascript·微信小程序·小程序
@PHARAOH1 小时前
HOW - 浏览器兼容(含 Safari)
前端·safari
undefined在掘金390411 小时前
flutter 仿商场_首页
前端
少卿1 小时前
react-native图标替换
前端·react native
熊猫钓鱼>_>1 小时前
TypeScript前端架构与开发技巧深度解析:从工程化到性能优化的完整实践
前端·javascript·typescript
Nick56831 小时前
Xcode16 避坑
ios
ii_best1 小时前
IOS/ 安卓开发工具按键精灵Sys.GetAppList 函数使用指南:轻松获取设备已安装 APP 列表
android·开发语言·ios·编辑器
2501_915909061 小时前
iOS 26 文件管理实战,多工具组合下的 App 数据访问与系统日志调试方案
android·ios·小程序·https·uni-app·iphone·webview
hweiyu001 小时前
苹果iOS开发零基础特训(视频教程)
ios