【Flutter入门练中学】第1课:从零开始

目标:先跑起来,再改代码,再故意犯错,最后看答案。


一、先跑起来:最小 Flutter 程序

创建项目:

bash 复制代码
flutter create my_first_app
cd my_first_app
flutter run -d chrome

把 lib/main.dart 改成:

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(
      home: Scaffold(
        body: Center(
          child: Text('Hello Flutter'),
        ),
      ),
    );
  }
}

在终端按 r 触发热重载,把文字改成 你好,Flutter,界面会立刻变化。

核心概念一句话:

· Widget:界面元素。

· Widget 树:Widget 层层嵌套。

· StatelessWidget:不可变,不能自己改自己。

· StatefulWidget:有状态,可通过 setState() 刷新界面。

· 热重载:改代码后按 r,不重启应用就能看到变化。


二、多元化习题

练习0:环境自检

题目要求

运行 flutter doctor,记录所有带 的项目,逐个解决。再次运行,直到全部变成

答案

常用命令:

bash 复制代码
flutter doctor
flutter doctor --android-licenses

常见问题:

· Android SDK 没装:安装 Android Studio。

· Chrome 没装:安装 Chrome。

· PATH 没配:把 Flutter 的 bin 目录加入环境变量。

· 许可证没接受:运行 flutter doctor --android-licenses。

答案解读

flutter doctor 是环境体检工具。它不自动修环境,但会告诉你缺什么。环境问题解决一次,后面开发会顺畅很多。


练习1:选择题

题目要求

在 Flutter 中,哪个 Widget 用于垂直排列子元素?

A. Row

B. Column

C. Stack

D. Center

答案

B。

答案解读

Row 是水平排列,Column 是垂直排列,Stack 是层叠布局,Center 是居中。做名片、列表、计数器时,最常用的就是 Column。


练习2:判断题

题目要求

判断对错,并说明理由:

  1. Flutter 中"一切皆 Widget"。
  2. StatelessWidget 可以通过 setState() 更新界面。

答案

  1. 对。
  2. 错。

答案解读

Flutter 的界面由 Widget 组成,文字、按钮、布局、间距都是 Widget。StatelessWidget 不可变,没有 setState();只有 StatefulWidget 的 State 中才能调用 setState() 触发重建。


练习3:连线题

题目要求

将左侧 Widget 与右侧作用连线:

左侧 右侧

Center 垂直排列

Column 显示文字

Text 居中

SizedBox 页面骨架

Scaffold 占位/间距

答案

· Center --- 居中

· Column --- 垂直排列

· Text --- 显示文字

· SizedBox --- 占位/间距

· Scaffold --- 页面骨架

答案解读

这些是入门最常用的 Widget。先记住作用,再通过组合搭界面。Flutter 开发就是不断把小组件拼成大组件。


练习4:排序题

题目要求

将以下 Widget 按"从外到内"的嵌套顺序排列:

Text、Scaffold、MaterialApp、Center

答案

MaterialApp → Scaffold → Center → Text

答案解读

MaterialApp 是应用外壳,Scaffold 是页面骨架,Center 让内容居中,Text 是最里面显示的文字。理解嵌套顺序,就理解了 Widget 树。


练习5:填空题

题目要求

补全代码,使文字居中显示"你好,Flutter":

dart 复制代码
body: ______(
  child: ______('你好,Flutter'),
),

答案

dart 复制代码
body: Center(
  child: Text('你好,Flutter'),
),

答案解读

Center 负责居中,Text 负责显示文字。body 是 Scaffold 的主体区域。如果直接写 body: Text(...),文字会顶到左上角。


练习6:代码预测题

题目要求

阅读代码,预测点击按钮 3 次后屏幕显示什么:

dart 复制代码
class Demo extends StatefulWidget {
  const Demo({super.key});
  @override
  State<Demo> createState() => _DemoState();
}

class _DemoState extends State<Demo> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$count'),
            ElevatedButton(
              onPressed: () => setState(() => count++),
              child: const Text('+1'),
            ),
          ],
        ),
      ),
    );
  }
}

答案

显示 3。

答案解读

初始 count = 0。每次点击执行 setState(() => count++),count 加 1,并通知 Flutter 重新构建界面。点 3 次后,count 变成 3,所以 Text('$count') 显示 3。


练习7:改错题

题目要求

下面代码有错误,找出来并修正:

dart 复制代码
void main() {
  runApp(MyApp);
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Text('练习7'),
      ),
    );
  }
}

答案

修正后:

dart 复制代码
void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: const Center(
          child: Text('练习7'),
        ),
      ),
    );
  }
}

答案解读

runApp(MyApp) 传入的是类名,不是 Widget 实例,应该写成 runApp(MyApp()) 或 runApp(const MyApp())。使用 const MyApp() 时,需要给 MyApp 添加 const MyApp({super.key}); 构造函数。另外,Text 直接放 body 会顶到左上角,通常包一层 Center。


练习8:补全代码题

题目要求

补全下面代码,实现计数器:点击按钮,数字加 1。

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

  @override
  State<Counter> createState() => ______;
}

class _CounterState extends State<Counter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$count', style: const TextStyle(fontSize: 48)),
            ElevatedButton(
              onPressed: () {
                ______(() {
                  ______;
                });
              },
              child: const Text('+1'),
            ),
          ],
        ),
      ),
    );
  }
}

答案

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

  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('$count', style: const TextStyle(fontSize: 48)),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  count++;
                });
              },
              child: const Text('+1'),
            ),
          ],
        ),
      ),
    );
  }
}

答案解读

createState() 返回 _CounterState()。按钮点击时用 setState() 包裹状态修改,count++ 让数字加 1。setState() 会触发 build 重新执行,界面更新。


练习9:动手编码题:个人名片

题目要求

用 Column、Text、SizedBox 做一个个人名片,显示三行信息:姓名、职业、城市。要求垂直排列,每行之间有间距。

答案

dart 复制代码
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: const [
      Text(
        '张三',
        style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
      ),
      SizedBox(height: 8),
      Text('Flutter 开发者'),
      SizedBox(height: 8),
      Text('青岛'),
    ],
  ),
),

答案解读

Column 垂直排列,Center 整体居中,SizedBox(height: 8) 制造间距。TextStyle 让姓名更突出。这个练习训练的是 Widget 组合能力。


练习10:动手编码题:点赞计数器

题目要求

做一个"收到 N 个赞"的页面,点击按钮 N 加 1。

答案

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

  @override
  State<LikeApp> createState() => _LikeAppState();
}

class _LikeAppState extends State<LikeApp> {
  int likes = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('收到 $likes 个赞', style: const TextStyle(fontSize: 24)),
            const SizedBox(height: 16),
            ElevatedButton.icon(
              onPressed: () {
                setState(() {
                  likes++;
                });
              },
              icon: const Icon(Icons.thumb_up),
              label: const Text('点赞'),
            ),
          ],
        ),
      ),
    );
  }
}

答案解读

likes 是可变状态,放在 State 中。点击按钮时 setState() 让 likes 加 1,界面中的 $likes 自动刷新。这个练习把"展示数据"和"修改数据"结合了起来。


练习11:综合挑战:名片 + 点赞

题目要求

把练习9和练习10合并:上面显示个人名片,下面显示"收到 N 个赞",点击按钮 N 加 1。

答案

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

  @override
  State<ProfileCard> createState() => _ProfileCardState();
}

class _ProfileCardState extends State<ProfileCard> {
  int likes = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              '张三',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            const Text('Flutter 开发者 · 青岛'),
            const SizedBox(height: 24),
            Text('收到 $likes 个赞', style: const TextStyle(fontSize: 18)),
            const SizedBox(height: 12),
            ElevatedButton.icon(
              onPressed: () {
                setState(() {
                  likes++;
                });
              },
              icon: const Icon(Icons.thumb_up),
              label: const Text('点赞'),
            ),
          ],
        ),
      ),
    );
  }
}

答案解读

静态信息直接写死,动态点赞数用 likes 保存。整个页面是 StatefulWidget,因为有点赞交互。setState() 只修改 likes,Flutter 自动重建相关部分。


练习12:开放式挑战:今日待办

题目要求

用 Text、Column、Center、SizedBox 设计一个"今日待办"页面。至少包含 5 个 Widget 嵌套,至少一处使用 TextStyle 做样式区分。

答案示例

dart 复制代码
body: Center(
  child: Padding(
    padding: const EdgeInsets.all(24),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: const [
        Text(
          '今日待办',
          style: TextStyle(
            fontSize: 28,
            fontWeight: FontWeight.bold,
            color: Colors.blue,
          ),
        ),
        SizedBox(height: 20),
        Text('1. 学习 Flutter 基础', style: TextStyle(fontSize: 18)),
        SizedBox(height: 10),
        Text(
          '2. 完成第1课习题',
          style: TextStyle(fontSize: 18, color: Colors.green),
        ),
        SizedBox(height: 10),
        Text(
          '3. 复习 Widget 树',
          style: TextStyle(
            fontSize: 18,
            decoration: TextDecoration.lineThrough,
          ),
        ),
        SizedBox(height: 30),
        Text(
          '加油,今天也要练中学!',
          style: TextStyle(
            fontSize: 16,
            fontStyle: FontStyle.italic,
            color: Colors.grey,
          ),
        ),
      ],
    ),
  ),
),

答案解读

这个页面包含 Center、Padding、Column、Text、SizedBox 多层嵌套,满足 Widget 树练习。TextStyle 分别做了标题加粗变蓝、完成项绿色、已完成项删除线、底部文字斜体灰色。开放题没有唯一答案,重点是能组合、能运行、能改样式。


练习13:错误观察挑战

题目要求

在任意一个能运行的例子中,故意删掉一个右括号,或把 Column 改成不存在的 Colum,运行后观察控制台错误。记录你看到的关键错误词。

答案

常见错误示例:

text 复制代码
Error: Expected ')' before this.

或:

text 复制代码
The method 'Colum' isn't defined for the type '_MyAppState'.

答案解读

Flutter 报错通常会给出文件名、行号和原因。新手最重要的能力之一,就是学会看错误关键词:Expected 表示缺少符号,isn't defined 表示名字写错,The named parameter ... isn't defined 表示参数名不对。故意改坏代码,再修好,是练中学非常有效的方法。


三、本课小结

这一课你完成了:

  1. 跑通第一个 Flutter 应用;
  2. 认识 Widget、Widget 树、StatelessWidget、StatefulWidget、setState、热重载;
  3. 做了 14 个练习,覆盖环境、选择、判断、连线、排序、填空、代码预测、改错、补全、动手编码、综合挑战、开放设计和错误观察。

下一课会进入布局系统:Row、Column、Container、Expanded、Padding、MainAxisAlignment,继续用"练中学"的方式搭出更复杂的界面。

相关推荐
小弥儿11 小时前
GitHub今日热榜 | 2026-09-18:腾讯双项目上榜
学习·开源
web守墓人12 小时前
【goed/ui】自定义组件设计思想篇
linux·windows·ui·golang
知识分享小能手13 小时前
深度学习学习教程,从入门到精通,深度生成模型 —— 知识点详解与代码实现(20)
人工智能·深度学习·学习
m4Rk_14 小时前
【论文阅读】Agent 记忆机制(74):CompassMem——从相似度检索走向事件图上的记忆导航
论文阅读·人工智能·学习·开源·github
小李不想当小白14 小时前
DMA直接存储器存取(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·分享
用户21816970493015 小时前
Flutter ClipPath
flutter
2601_9499506316 小时前
练题簿在线练题全流程:从资料导入到模拟考试与错题复盘
学习·考研·小程序·刷题·小程序推荐
惟恋惜16 小时前
第 3 章 · 列表、滚动与 Lazy 深入:告别 RecyclerView 思维
ui·android jetpack
别动我齐刘海16 小时前
ROS2 Jazzy + C++ 实战路线——基础学习2
c++·人工智能·vscode·python·学习·机器学习·机器人