Flutter基础入门:从零开始构建你的第一个应用
本教程专为Flutter初学者设计,带你从零开始掌握Flutter的核心概念与开发流程。我们将通过循序渐进的方式,结合可运行的单文件示例,帮助你理解Widget、State管理、布局系统以及事件处理等关键知识点。无论你是移动开发新手,还是有经验的程序员希望转型跨平台开发,本教程都将为你打下坚实的基础。
在本篇教程中,你将学会如何使用 main() 函数启动一个Flutter应用,利用 MaterialApp 构建Material风格界面,使用 Scaffold 快速搭建页面结构,并通过 StatefulWidget 和 setState() 实现动态交互。我们还会深入讲解常见的布局组件如 Column、Row、Container 等的实际用法。
整个学习路径分为三个阶段:
- 第一阶段:环境准备与Hello World
- 第二阶段:理解Widget树与基本布局
- 第三阶段:实现交互式UI与状态更新
每个阶段都配有完整的、可独立运行的Dart代码文件,文件名前缀对应章节编号,便于你逐个执行和调试。
第一阶段:环境准备与Hello World
在开始编写代码之前,请确保你已经安装了以下工具:
- Flutter SDK(推荐最新稳定版)
- 支持Flutter的编辑器(如 VS Code 或 Android Studio)
- 模拟器或真机用于运行应用
步骤1:创建Flutter项目
打开终端,执行以下命令创建一个新的Flutter项目:
flutter create flutter_tutorial_01
进入项目目录:
cd flutter_tutorial_01
步骤2:替换 lib/main.dart 文件内容
我们将从最简单的“Hello World”程序开始。删除原有代码,写入以下内容:
// 文件名:01_hello_world.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 教程',
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('第一课:Hello World')),
body: const Center(
child: Text(
'你好,Flutter!',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
);
}
}
关键字高亮说明
main():这是Dart程序的入口函数,必须存在。runApp():启动Flutter应用,接收一个Widget作为根节点。MaterialApp:提供Material Design视觉风格的应用容器,包含路由、主题等功能。Scaffold:实现基本的Material Design页面布局结构,包括AppBar、Body、FloatingActionButton等。Center和Text:基础Widget,用于居中显示文本内容。
执行效果
保存文件后,在终端运行:
flutter run
你应该看到一个带有蓝色标题栏的应用,中间显示“你好,Flutter!”的文字。

这个案例虽然简单,但它展示了Flutter应用的基本骨架:入口函数 → 根组件 → 页面结构 → 内容展示。
第二阶段:理解Widget树与基本布局
Flutter的核心理念是“一切皆为Widget”。每一个UI元素都是一个Widget,它们以树形结构组合在一起,形成最终的用户界面。
我们将在这个阶段学习如何使用 Column、Row、Container 和 Padding 来构建更复杂的布局。
步骤3:创建带布局结构的页面(文件名:02_layout_basics.dart)
// 文件名:02_layout_basics.dart
import 'package:flutter/material.dart';
void main() {
runApp(const LayoutApp());
}
class LayoutApp extends StatelessWidget {
const LayoutApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: '布局基础',
home: LayoutScreen(),
);
}
}
class LayoutScreen extends StatelessWidget {
LayoutScreen({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('第二课:布局基础')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
color: Colors.lightBlue,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: const Text(
'顶部信息区',
style: TextStyle(color: Colors.white, fontSize: 18),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildIconCard(Icons.star, '收藏', Colors.orange),
_buildIconCard(Icons.favorite, '喜欢', Colors.red),
_buildIconCard(Icons.share, '分享', Colors.green),
],
),
const SizedBox(height: 20),
const Text(
'详细描述:\n这是一段关于当前内容的详细介绍文字,展示如何在Flutter中使用文本和布局控件。',
style: TextStyle(fontSize: 16),
)
],
),
),
);
}
// 提取为独立函数,提升代码复用性
Widget _buildIconCard(IconData icon, String label, Color color) {
return Column(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, size: 32, color: color),
),
const SizedBox(height: 8),
Text(label, style: TextStyle(fontSize: 14, color: color))
],
);
}
}
布局核心概念解析
Column:垂直排列子Widget,常用于上下结构布局。Row:水平排列子Widget,适合并排展示内容。Container:通用容器,支持设置宽高、边距、背景色、圆角等样式。Padding:为子Widget添加内边距。SizedBox:用于插入固定大小的空间,比如间隔。
我们还定义了一个私有函数 _buildIconCard,它接受图标、标签和颜色参数,返回一个统一风格的卡片Widget。这种做法体现了函数封装的重要性,让代码更清晰、易维护。
运行效果
执行该文件后,你会看到如下界面:

页面包含一个蓝色标题栏、顶部信息块、三张功能图标卡和一段描述文本。这正是典型的移动应用详情页布局雏形。
第三阶段:实现交互式UI与状态更新
静态页面只是起点,真正的应用需要响应用户的操作。这就涉及到状态管理。
在Flutter中,有两类主要的组件:
StatelessWidget:无状态组件,一旦创建就不会改变。StatefulWidget:有状态组件,可以随用户交互或数据变化而刷新UI。
我们将创建一个计数器应用,演示如何使用 StatefulWidget 和 setState() 方法来更新界面。
步骤4:创建交互式计数器应用(文件名:03_interactive_counter.dart)
// 文件名:03_interactive_counter.dart
import 'package:flutter/material.dart';
void main() {
runApp(const CounterApp());
}
class CounterApp extends StatelessWidget {
const CounterApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: '交互式计数器',
theme: ThemeData(primarySwatch: Colors.purple),
home: const CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
const CounterScreen({super.key});
State<CounterScreen> createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _decrementCounter() {
setState(() {
if (_counter > 0) {
_counter--;
}
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('第三课:交互式计数器')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'点击按钮增减数值:',
style: TextStyle(fontSize: 18, color: Colors.grey),
),
const SizedBox(height: 20),
Text(
'$_counter',
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: _counter == 0 ? Colors.grey : Colors.purple,
),
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: _decrementCounter,
icon: const Icon(Icons.remove),
label: const Text('减少'),
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
),
const SizedBox(width: 20),
ElevatedButton.icon(
onPressed: _resetCounter,
icon: const Icon(Icons.refresh),
label: const Text('重置'),
style: ElevatedButton.styleFrom(backgroundColor: Colors.orange),
),
const SizedBox(width: 20),
ElevatedButton.icon(
onPressed: _incrementCounter,
icon: const Icon(Icons.add),
label: const Text('增加'),
style: ElevatedButton.styleFrom(backgroundColor: Colors.green),
),
],
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: '增加',
child: const Icon(Icons.add),
),
);
}
}
核心机制详解
StatefulWidget:当组件需要根据用户操作更新自身时,应继承此类。createState():必须实现的方法,返回对应的State对象。State类:持有组件的状态变量(如_counter)和更新逻辑。setState():这是触发UI重建的关键方法。只有调用它,Flutter才会重新调用build()并更新屏幕。
我们在代码中定义了三个操作函数:
_incrementCounter():计数加1_decrementCounter():计数减1(防止负数)_resetCounter():重置为0
这些函数都被绑定到按钮的 onPressed 事件上,实现了完整的交互闭环。
运行效果
启动应用后,初始显示0,点击“增加”按钮数字上升,“减少”下降,“重置”归零。FAB(悬浮按钮)也绑定增加功能。

此外,数字的颜色会根据值变化:为0时灰色,非0时紫色,增强了视觉反馈。
综合案例:天气卡片交互应用(文件名:04_weather_demo.dart)
为了巩固前面所学知识,我们来做一个稍复杂的综合案例——模拟天气卡片,包含温度显示、状态切换和动画提示。
// 文件名:04_weather_demo.dart
import 'package:flutter/material.dart';
void main() {
runApp(const WeatherApp());
}
class WeatherApp extends StatelessWidget {
const WeatherApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: '天气应用示例',
home: const WeatherScreen(),
debugShowCheckedModeBanner: false,
);
}
}
class WeatherScreen extends StatefulWidget {
const WeatherScreen({super.key});
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
bool _isCelsius = true;
bool _isLoading = false;
void _toggleTemperatureUnit() {
setState(() {
_isLoading = true;
});
// 模拟网络延迟
Future.delayed(const Duration(seconds: 1), () {
setState(() {
_isCelsius = !_isCelsius;
_isLoading = false;
});
});
}
double _getTemperatureInFahrenheit(double celsius) {
return celsius * 9 / 5 + 32;
}
Widget build(BuildContext context) {
final tempInCelsius = 26.0;
final tempInFahrenheit = _getTemperatureInFahrenheit(tempInCelsius);
return Scaffold(
appBar: AppBar(
title: const Text('第四课:天气卡片 demo'),
centerTitle: true,
),
body: Center(
child: _isLoading
? const CircularProgressIndicator()
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
_isCelsius ? Icons.sunny : Icons.nightlight,
size: 80,
color: _isCelsius ? Colors.orange : Colors.blue,
),
const SizedBox(height: 20),
Text(
_isCelsius
? '${tempInCelsius.toStringAsFixed(1)}°C'
: '${tempInFahrenheit.toStringAsFixed(1)}°F',
style: const TextStyle(fontSize: 40, fontWeight: FontWeight.w500),
),
const SizedBox(height: 10),
Text(
_isCelsius ? '摄氏度' : '华氏度',
style: const TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: _toggleTemperatureUnit,
child: Text(_isCelsius ? "切换为华氏度" : "切换为摄氏度"),
)
],
),
),
);
}
}
功能亮点
- 使用
bool _isCelsius控制温度单位状态。 - 切换时显示
CircularProgressIndicator模拟加载过程。 - 利用
Future.delayed模拟异步请求场景。 - 图标和颜色随模式变化,提升用户体验。
运行效果
初始显示26°C,点击按钮后进入加载状态,1秒后变为约78.8°F。

切换后界面更新:

这个案例融合了状态管理、条件渲染、异步操作和UI反馈,是进阶学习的良好起点。
总结
通过本篇教程的四个阶段,你已经完成了从“Hello World”到交互式应用的完整跃迁。我们严格遵循了以下学习路径:
- 环境搭建与项目初始化:掌握
main()和runApp()的作用。 - 布局系统深入理解:熟练使用
Column、Row、Container等构建复杂界面。 - 状态管理实战:通过
StatefulWidget和setState()实现动态交互。 - 综合案例演练:整合知识点完成模拟真实场景的应用。
在整个过程中,我们始终坚持以下原则:
- 严格使用函数:将重复UI提取为独立Widget函数,提高可读性和复用性。
- 关键字高亮强调:突出
StatefulWidget、setState、build等核心概念。 - 分阶段递进教学:由浅入深,每一步都有明确目标。
- 单文件可执行案例:每个代码片段均可直接复制运行,降低学习门槛。
你现在已具备开发简单Flutter应用的能力。下一步建议探索:
- 导航与路由(
Navigator.push) - 表单输入与验证
- 网络请求(
http包) - 更高级的状态管理方案(Provider、Riverpod、Bloc)
记住,Flutter的学习曲线前期陡峭,但一旦掌握其声明式UI和响应式编程范式,开发效率将大幅提升。坚持动手实践,不断重构优化代码,你会很快成长为一名优秀的Flutter开发者。
🌟 小贴士:每次写完代码后,尝试问自己:“这部分能不能封装成函数?”、“状态是否合理?”、“有没有冗余Widget?”,这将极大提升你的工程思维。
Happy Coding with Flutter!

被折叠的 条评论
为什么被折叠?



