第一讲 Flutter核心思想与基础布局

前言:

没什么好说的,别说AI来了这些技术不重要,AI是生产力工具,你真一点不懂,凭什么有竞争力,人家能发现AI生成的问题,你发现不了,你就Out了。

Flutter25讲,不会讲得很深,但一定全,入门一定快。力求在AI时代,让你快速的学会Flutter的全局,纲举目张后,俯瞰之下,再开发,事半功倍。

这也是作为一个后端架构师,在修行前端的经验之路。

一 核心思想:一切皆 Widget

Flutter 中没有「控件/视图/布局」的区分,所有可见的UI元素(文字、按钮、图片)、不可见的逻辑元素(主题、路由、手势检测)、布局容器(Row、Column)本质上都是 Widget。

可以把 Widget 理解为:描述UI的「配置信息」,Flutter 会根据这些配置构建出真正的渲染对象(RenderObject)。

关键特点

  • Widget 是不可变的(immutable):一旦创建就不能修改属性,更新UI需要创建新的 Widget
  • Widget 是轻量级的:仅保存配置信息,不直接参与渲染
  • 组合式设计:复杂UI由多个简单 Widget 嵌套组合而成

二 布局核心原则:约束向下传递,尺寸向上返回

这是 Flutter 布局的「黄金法则」,决定了所有 Widget 的大小计算逻辑:

1. 约束向下传递

父 Widget 会给子 Widget 传递一组「约束条件」(比如最大/最小宽高、是否强制填充),子 Widget 必须在这个约束范围内确定自己的尺寸。

  • 示例:Row 会告诉子 Widget「你可以在我的横向空间内调整宽度,但高度和我一致」
  • 通俗理解:父母给孩子划定了活动范围,孩子不能超出这个范围

2. 尺寸向上返回

子 Widget 根据父 Widget 的约束,计算出自己的实际尺寸后,把这个尺寸返回给父 Widget,父 Widget 再决定如何摆放这个子 Widget(比如居中、靠左)。

可视化流程

三 基础布局组件实战

核心组件

基础组件(Container/Center/Align/SizedBox)是布局的基石,用于控制单个组件的尺寸、位置和样式。

(1)Container:万能容器

Container 是最常用的基础组件,可设置宽高、背景、边距、内边距、装饰等,相当于「盒子」。

示例代码:

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('基础布局实战')),
        body: Container(
          // 宽高(受父约束限制)
          width: 200,
          height: 200,
          // 背景色
          color: Colors.blue[100],
          // 内边距(内容与容器边界的距离)
          padding: const EdgeInsets.all(16),
          // 外边距(容器与其他组件的距离)
          margin: const EdgeInsets.only(left: 20, top: 30),
          // 装饰(优先级高于color,二选一)
          decoration: BoxDecoration(
            border: Border.all(color: Colors.blue, width: 2),
            borderRadius: BorderRadius.circular(10), // 圆角
          ),
          // 子组件
          child: const Text(
            '我是Container的子组件',
            style: TextStyle(fontSize: 18),
          ),
        ),
      ),
    );
  }
}

关键属性说明:

  • width/height:设置容器尺寸(若不设置,会自适应子组件或父约束)

  • padding/margin:内边距/外边距,使用 EdgeInsets 配置(all/left/top/symmetric 等)

  • color/decoration:背景色/装饰(不能同时设置,decoration 功能更丰富,支持边框、圆角、渐变等),color 本质是 decoration: BoxDecoration(color: color) 的简写形式。两者不能共存,否则会触发断言 color == null || decoration == null 失败

(2)Center:居中组件

将子组件在自身范围内水平+垂直居中,是 Align 的简化版(对齐方式固定为居中)。

示例代码:

less 复制代码
// 替换上面的body部分
body: Container(
  width: 300,
  height: 300,
  color: Colors.grey[200],
  child: const Center(
    child: Text('我居中显示'),
  ),
),

(3)Align:对齐组件

可自定义子组件的对齐位置(如靠左上、靠右下、居中),比 Center 更灵活。

示例代码:

less 复制代码
// 替换body部分
body: Container(
  width: 300,
  height: 300,
  color: Colors.grey[200],
  child: const Align(
    // 对齐方式:右下(可选topLeft、center、bottomRight等)
    alignment: Alignment.bottomRight,
    // 也可使用百分比:Alignment(0.8, 0.8) (x/y范围-1到1)
    child: Text('我在右下角'),
  ),
),

(4)SizedBox:固定尺寸组件

强制设置子组件的宽高,或仅占指定空间(无子女时),常用于控制组件间距。

示例代码:

php 复制代码
// 替换body部分
body: Column(
  children: [
    const Text('上方文字'),
    // 占16px高度的空白,用于分隔
    const SizedBox(height: 16),
    // 强制子组件宽高为100px
    SizedBox(
      width: 100,
      height: 100,
      child: Container(color: Colors.red[100]),
    ),
  ],
),

SizedBox在开发中基本都以空白的身份出现,作为上下或者左右的一个间隔符,一般使用const声明,减少损耗。

常用布局容器

常用布局容器(Row/Column/Stack+Positioned)用于实现多组件的线性/层叠排列,是构建复杂UI的核心。

(1)Row:水平布局(行)

将子组件沿水平方向排列,核心是「线性布局」,类似 Android 的 LinearLayout(horizontal)。

示例代码:

php 复制代码
  body: Row(
    // 主轴(水平)对齐方式:spaceBetween(两端对齐,中间均分)
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    // 交叉轴(垂直)对齐方式:center
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      Container(width: 80, height: 80, color: Colors.red[100]),
      Container(width: 80, height: 100, color: Colors.green[100]),
      Container(width: 80, height: 80, color: Colors.blue[100]),
    ],
  ),

关键属性说明:

  • mainAxisAlignment:主轴(Row为水平)对齐方式

    • start:靠左(默认)、end:靠右、center:居中、spaceBetween:两端对齐、spaceAround:均匀分布(含左右边距)
  • crossAxisAlignment:交叉轴(Row为垂直)对齐方式

    • start:靠上、end:靠下、center:居中(默认)、stretch:拉伸填满交叉轴,可以改变一下,看看这几个的差别

(2)Column:垂直布局(列)

将子组件沿垂直方向排列,与 Row 逻辑一致,仅主轴方向不同(Column 主轴为垂直)。

示例代码:

less 复制代码
// 替换body部分
body: Padding(
  padding: const EdgeInsets.all(20),
  child: Column(
    // 主轴(垂直)对齐方式:center
    mainAxisAlignment: MainAxisAlignment.center,
    // 交叉轴(水平)对齐方式:stretch(拉伸填满)
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Container(height: 60, color: Colors.red[100]),
      const SizedBox(height: 10),
      Container(height: 60, color: Colors.green[100]),
      const SizedBox(height: 10),
      Container(height: 60, color: Colors.blue[100]),
    ],
  ),
),

可以看到,CrossAxisAlignment(交叉轴)属性,如果是行,他与高绑定,如果是列,他与宽绑定,这点要注意。

(3)Stack + Positioned:层叠布局

  • Stack:让子组件层叠显示(后添加的组件在上方),理解一下概念,铺床,一层一层的,先铺的在下面,看到的是后面的。
  • Positioned:配合 Stack 使用,精准定位子组件的位置(左、右、上、下、宽高)

Positioned 关键属性:

  • left/right/top/bottom:距离 Stack 对应边界的距离(至少设置2个方向+宽/高,或4个方向)
  • width/height:定位组件的尺寸

示例代码:

less 复制代码
// 替换body部分
body: Stack(
  children: [
    // 底层容器
    Container(
      width: 300,
      height: 300,
      color: Colors.grey[200],
    ),
    // 定位在左上角
    const Positioned(
      left: 20,
      top: 20,
      child: Text('左上角文字'),
    ),
    // 定位在右下角,指定宽高
    Positioned(
      right: 20,
      bottom: 20,
      width: 100,
      height: 100,
      child: Container(color: Colors.red[100]),
    ),
    // 定位在右下角,指定宽高
    Positioned(
      right: 20,
      bottom: 20,
      width: 80,
      height: 80,
      child: Container(color: Colors.blue[100]),
    ),
  ],
),

四 组合布局实现简单卡片

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('组合布局实战')),
        body: Padding(
          padding: const EdgeInsets.all(16),
          child: Container(
            width: double.infinity, // 拉伸填满父宽度
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(12),
              boxShadow: const [
                BoxShadow(color: Colors.grey, blurRadius: 3, offset: Offset(0, 2))
              ],
            ),
            child: Row(
              children: [
                // 左侧图标
                Container(
                  width: 60,
                  height: 60,
                  decoration: BoxDecoration(
                    color: Colors.blue[100],
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: const Icon(Icons.person, size: 30, color: Colors.blue),
                ),
                // 中间间距
                const SizedBox(width: 16),
                // 右侧文字区域(垂直排列)
                Expanded( // 占满剩余水平空间
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: const [
                      Text('用户名', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                      SizedBox(height: 4),
                      Text('用户ID:123456', style: TextStyle(fontSize: 14, color: Colors.grey)),
                    ],
                  ),
                ),
                // 右侧箭头
                const Icon(Icons.arrow_forward_ios, size: 16, color: Colors.grey),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

案例说明:

  • 用 Container 实现卡片样式(圆角、阴影)
less 复制代码
          child: Container(
            width: double.infinity, // 拉伸填满父宽度
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(12),
              boxShadow: const [
                BoxShadow(color: Colors.grey, blurRadius: 3, offset: Offset(0, 2))
              ],
            ),
            child:Row()), 
  • 用 Row 实现水平布局(图标+文字+箭头)
scss 复制代码
Row(
    children:[
        //左侧图标
        Container(),
        //中间间距
        SizedBox(),
        //右侧文字区域
        Expanded(),
        //右侧箭头
        Icon()
    ]
)
  • 用 Expanded 让文字区域占满剩余空间(避免溢出)
  • 用 SizedBox 控制组件间距
  • 用 Column 实现文字的垂直排列
less 复制代码
                Expanded( // 占满剩余水平空间
                  child: Column(
                    crossAxisAlignment:  CrossAxisAlignment.start,
                    children: const [
                      Text('用户名', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                      SizedBox(height: 4),
                      Text('用户ID:123456', style: TextStyle(fontSize: 14, color: Colors.grey)),
                    ],
                  ),
                ),

五 常见问题

  1. 组件溢出 :Row/Column 子组件总尺寸超过父约束时,会出现黄色溢出警告 → 解决方案:使用 Expanded/Flexible 分配空间,或限制子组件尺寸
  2. 约束冲突:同时设置过严的约束(如父强制宽度200,子设置宽度300)→ 子组件会忽略自身约束,适配父约束
  3. Stack 子组件未定位:未使用 Positioned 的子组件,会默认居中显示,且尺寸自适应内容
相关推荐
yuanlaile6 小时前
2026年全新Flutter 跨平台开发全栈学习资料整理
flutter·getx·鸿蒙 next·flutter开发鸿蒙·flutter入门实战·flutter全栈
恋猫de小郭17 小时前
Genkit Dart 1.0 发布,Flutter 原生的 AI Agent 终于完整了
android·前端·flutter
第10086个小白17 小时前
flutter桌面端打包方式(Inno Setup Compiler)版本
前端·flutter
陆断枫1 天前
Flutter 3.47 动画引擎盘点:Impeller 全平台,和那些"新特性"
flutter
程序员老刘1 天前
Flet 1.0 思路很好,可惜来晚了
flutter·ai编程·客户端
m0_738185822 天前
Flutter 鸿蒙化实战:qr_code_scanner_plus 适配 OpenHarmony,二维码扫描
flutter·华为·harmonyos·鸿蒙
恋猫de小郭2 天前
Flutter + EmbeddingGemma 2,谷歌发布完全端侧的 AI Edge Foresight
android·前端·flutter
君赏2 天前
基于 FlutterPatch 快速接入 Flutter 热更新
flutter
律宏阔2 天前
Dart FFI 内存管理:用 using + Arena 替代嵌套 try-finally
前端·flutter
律宏阔2 天前
Flutter 调用 Go:从 c-shared + ffigen 到 @Native + Native Assets 踩坑记录
前端·flutter