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),让你的布局能力再上一个台阶!我们下篇见!

相关推荐
lifejump2 小时前
DVWA | XSS 跨站脚本注入
前端·xss
gplitems1232 小时前
Tripfery - Travel & Tour Booking WordPress Theme Tested
前端
流星稍逝2 小时前
前端&后端解决跨域的方法
前端·后端
白水清风2 小时前
【基础】关于函数式编程的知识
前端·javascript·面试
蓝莓味的口香糖2 小时前
【JS】JS基础-对象处理方法整合
开发语言·前端·javascript
sanx183 小时前
一站式电竞平台解决方案:数据、直播、源码,助力业务飞速启航
前端·数据库·apache·数据库开发·时序数据库
余防3 小时前
存储型XSS,反射型xss
前端·安全·web安全·网络安全·xss
ObjectX前端实验室3 小时前
从零到一:系统化掌握大模型应用开发【目录】
前端·llm·agent
guoyp21263 小时前
前端实验(二)模板语法
前端·vue.js