目录

核心知识点

一、核心组件

1.  StatefulWidget(有状态组件)

1.1 与StatelessWidget的核心区别

1.2 结构格式

2. 布局组件:Column

3. 布局组件:Expanded

4. 容器组件:Container

二、待办清单主页

三、代码详解

1. 项目结构优化

2. Scaffold的使用

3. 主页布局的核心逻辑

4. 样式优化细节

结尾


        目标:基于Scaffold完善待办清单的主界面布局,实现标题栏 + 任务列表区域 + 悬浮添加按钮的完整页面框架,为后续功能预留交互区域。

核心知识点

  • Scaffold组件的完整属性使用(appBar/body/floatingActionButton
  • Flutter 基础布局组件:ColumnContainerPaddingExpanded
  • 布局核心属性:crossAxisAlignmentmainAxisSizemainAxisAlignment

一、核心组件

1.  StatefulWidget(有状态组件)

1.1 与StatelessWidget的核心区别

组件类型 状态是否可变 build 方法执行时机 适用场景
StatelessWidget 不可变 仅创建时执行一次 静态 UI、根容器、无交互组件
StatefulWidget 可变 创建时和 setState时执行 有交互、数据变化的组件

1.2 结构格式

class 组件名 extends StatefulWidget {
  const 组件名({super.key}); // 构造函数
  @override
  State<组件名> createState() => _组件名State(); // 创建状态类
}
// 状态类:下划线表示私有,仅在当前文件中可用
class _组件名State extends State<组件名> {
  // 存放可变状态(如任务列表、输入框控制器)
  @override
  Widget build(BuildContext context) {
    // 构建UI,可使用可变状态
    return Container();
  }
}

使用原因

        待办清单的主界面包含输入框任务列表,内容会随用户操作(输入、添加任务)变化,因此需要用StatefulWidget管理可变状态。

2. 布局组件:Column

  • 作用:垂直布局组件,将子 Widget 按从上到下的顺序排列在垂直方向
  • 核心属性:
    • children:子 Widget 数组,存放需要排列的所有组件
    • crossAxisAlignment交叉轴对齐(Column 的主轴是垂直方向,交叉轴是水平方向),常用值:
      • CrossAxisAlignment.start:左对齐
      • CrossAxisAlignment.center:水平居中
      • CrossAxisAlignment.stretch:水平拉伸,占满父容器宽度(本次核心使用)
    • mainAxisAlignment主轴对齐(垂直方向),常用值:start/center/end/spaceBetween
    • mainAxisSize:主轴尺寸,MainAxisSize.min(包裹子组件)/MainAxisSize.max(占满父容器高度,默认)
  • 易错点:Column的子组件如果高度超过屏幕,会导致布局溢出,需要配合Expanded使用。

替换body的内容:

// 页面主体内容区域:简单的文本内容
        body: Container(
          //width: double.infinity, // 占满整个宽度
          child: Column(
            // 垂直方向居中对齐
            mainAxisAlignment: MainAxisAlignment.center,
            // 水平方向居中对齐
            crossAxisAlignment: CrossAxisAlignment.center, // 水平居中
            children: [
              Text('待办事项页面'),
              Text('你好'),
            ],
          ),
        ),

CrossAxisAlignment.center没有效果的原因:

  • Column 宽度问题 : Column 默认宽度是包裹内容的,所以如果子元素是文本,整个 Column 就会收缩到文本的宽度
  • 水平居中效果 :当 Column 宽度等于内容宽度时, crossAxisAlignment: CrossAxisAlignment.center 就看不出效果了,因为内容已经填满了 Column 的宽度

解决方法:使用 Container 包裹 Column,并将 Container 宽度设置为占满整个宽度

width: double.infinity, // 占满整个宽度

3. 布局组件:Expanded

  • 作用:占满父容器剩余空间,通常配合Column/Row使用,解决布局溢出问题
  • 核心属性:child:包裹需要占满剩余空间的子 Widget
  • 使用场景:让任务列表区域占满输入框下方的所有剩余垂直空间,避免溢出。

假设你手机屏幕是一个竖版的长方形盒子(Column 垂直布局):

  • 盒子上半部分放了待办事项的输入框(占了固定高度)
  • 剩下的空白区域你想全部用来显示待办列表

        如果直接把列表塞进去,要么列表内容太多会 “撑破” 屏幕(溢出),要么列表内容少会留一大片空白。这时候给列表套上 Expanded,就相当于跟 Flutter 说:“把输入框用完剩下的所有空间,都分给这个列表!”

4. 容器组件:Container

  • 作用:通用容器组件,用于包裹其他 Widget,实现宽高、背景、边框、圆角、边距等样式设置
  • 核心属性:
    • child:包裹的子 Widget
    • margin:外间距(与其他 Widget 的距离)
    • padding:内间距(与子 Widget 的距离)
      • EdgeInsets.all(double value):上下左右均为 value 像素
      • EdgeInsets.symmetric(horizontal: x, vertical: y):水平方向 x,垂直方向 y
      • EdgeInsets.only(left: x, top: y, right: z, bottom: w):自定义四个方向的间距
      • EdgeInsets.fromLTRB(x, y, z, w):左、上、右、下依次设置
    • decoration:装饰样式(背景色、边框、圆角、阴影等)
      • color 背景颜色
      • border 边框样式
      • borderRadius 圆角半径
      • boxShadow 阴影效果
      • gradient 渐变背景
    • width /    height:固定宽高
      • width: 300  固定宽度
      • width: double.infinity - 占满父容器宽度
      • height: 300  固定高度

        是 Flutter 中使用最频繁的组件之一。

body: Center(
          child: Container(
            //宽度和高度
            width: 300, // 固定宽度
            height: 120, // 固定高度
            //外间距(与其他组件的距离)
            margin: EdgeInsets.all(20), // 四周外间距20
            //内间距(与子组件的距离)
            padding: EdgeInsets.all(16), // 四周内间距16
            //装饰样式
            decoration: BoxDecoration(
              // 背景色
              color: Colors.white,
              // 边框
              border: Border.all(
                color: Colors.blue, // 边框颜色
                width: 2, // 边框宽度
              ),
              // 圆角
              borderRadius: BorderRadius.circular(12), // 12px圆角
              // 阴影
              boxShadow: [
                BoxShadow(
                  color: Color.fromRGBO(128, 128, 128, 0.3), // 阴影颜色(半透明)
                  spreadRadius: 2, // 阴影扩散范围
                  blurRadius: 5, // 阴影模糊程度
                  offset: Offset(0, 3), // 阴影偏移(x, y)
                ),
              ],
            ),

            // 核心属性5:子组件
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Text('Container示例'),
                Text('展示所有核心属性'),
              ],
            ),
          ),
        ),

Column 宽度继承 :

        当 Column 作为 Container 的子组件时,它的宽度默认会继承父容器的宽度,所以这里可以水平居中。

二、待办清单主页

        将刚才所了解到的知识综合起来,就可以写出一个页面,之后再一点一点填内容。

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '待办事项',
      debugShowCheckedModeBanner: false,
      // 应用主页:设置为Scaffold(页面基础布局组件)
      home: const ToDoHomePage(),
    );
  }
}

class ToDoHomePage extends StatefulWidget {
  const ToDoHomePage({Key? key}) : super(key: key);

  @override
  State<ToDoHomePage> createState() => _ToDoHomePageState();
}

class _ToDoHomePageState extends State<ToDoHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('待办事项'),
        centerTitle: true,
        backgroundColor: Colors.blue,
      ),
      body: Container(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            //先空着,等讲到输入框时在添加
            Container(),
            // 待办事项列表区域
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  // 边框:灰色浅边,宽度1像素
                  border: Border.all(color: Colors.grey.shade200, width: 1),
                  // 圆角:8像素,柔和边角
                  borderRadius: BorderRadius.circular(8.0),
                  // 背景色:浅灰色,区分列表区域和页面背景
                  color: Colors.grey.shade50,
                ),
                child: Center(
                  child: Text(
                    '暂无待办事项',
                    style: TextStyle(
                      color: Colors.grey.shade400,
                      fontSize: 16.0,
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.blue,
        child: const Icon(Icons.add),
        onPressed: () {},
      ),
    );
  }
}

        效果:

三、代码详解

1. 项目结构优化

        将主页面抽离为独立的ToDoHomePage组件,根组件MyToDoApp仅做全局配置,符合模块化开发原则,后续新增页面时更易维护。

        继承StatefulWidget有状态组件,之后会通过输入框任务列表,根据用户操作(输入、添加任务)内容会发生变化,因此需要管理可变状态。现在页面还没有更改状态,因为我们还没有写对应事件,之后会一点一点添加。

2. Scaffold的使用

本次用到了Scaffold的三个核心属性,也是开发中最常用的:

  • appBar:顶部导航栏,添加了elevation属性设置阴影,提升页面层次感
  • body:页面主体,嵌套了Container+Column+Expanded,实现规范的布局
  • floatingActionButton:悬浮添加按钮,使用 Material Design 内置的Icons.add图标,点击事件onPressed后续实现

3. 主页布局的核心逻辑

Scaffold.body 
→ Container 
→ Column(垂直布局)
→ 两个子组件:
1. 添加输入框,现在先空着,Container → TextField
2. Expanded → Container(任务列表区域,占满剩余空间)

4. 样式优化细节

为了让界面更美观、符合 Material Design 规范,添加了多个细节样式:

  • 全局内间距:Padding(all:16),避免内容贴边
  • 列表区域样式:边框、圆角、浅背景色,区分页面背景,提升视觉体验
  • 暂无任务提示:灰色文字,居中显示,提升用户体验

结尾

        至此,已经完成了待办清单主界面的核心布局搭建 —— 从无状态的基础页面,升级为包含Scaffold完整属性、Column+Expanded布局逻辑、Container样式美化的有状态页面框架。不仅是实现了 “标题栏 + 输入框占位 + 任务列表区域 + 悬浮按钮” 的视觉效果,更重要的是掌握了 Flutter 布局的核心思维:

  • StatefulWidget为后续的 “数据变化”(输入、添加任务)预留了状态管理能力;
  • Column+Expanded解决了 “剩余空间占满” 的布局难题,避免了移动端常见的溢出问题;
  • Container的样式配置让界面脱离 “原生默认感”;
  • 用模块化的组件拆分(抽离ToDoHomePage),为后续功能拓展打下了可维护的基础。

        这个看似简单的页面框架,其实已经覆盖了 Flutter 日常开发中 80% 的基础布局场景:垂直排列、剩余空间分配、样式美化、有状态组件管理。接下来,你只需要逐步填充 “输入框输入任务”“点击悬浮按钮添加任务”“列表展示任务” 等核心功能,就能让这个静态框架变成可交互的完整应用。

        欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐