学习 Flutter (一)
学习 Flutter (一)
1. 引言
-
什么是 Flutter?
Flutter 是 Google 开发的一套开源 UI 框架,主要用于构建高性能、高保真、跨平台的应用程序。使用一套 Dart 编写的代码,开发者可以同时构建适用于:
-
Android
-
iOS
-
Web
-
Windows、macOS、Linux 桌面端
-
嵌入式平台(如车载、IoT 设备)
Flutter 的核心特性包括:
-
热重载(Hot Reload):可以快速预览修改结果,提高开发效率。
-
自绘式渲染引擎(Skia):绕过原生控件,确保 UI 在各平台一致。
-
丰富的组件库(Widgets):一切皆组件,易于构建复杂界面。
-
灵活的布局系统:支持响应式和复杂嵌套的布局设计。
-
-
为什么选择 Flutter?
选择 Flutter 的理由主要包括以下几点:
-
跨平台统一开发
用一套 Dart 代码即可构建多端应用,极大节省开发和维护成本。
-
高性能
Flutter 拥有自己的渲染引擎,不依赖原生控件,性能接近原生,尤其适合需要高帧率渲染的场景。 -
快速开发体验
热重载和热重启机制,加快了开发调试的迭代周期,提升开发效率。 -
丰富的生态
Flutter 拥有大量开源插件(如 camera、http、firebase 等),支持多数主流功能的快速集成。 -
社区支持良好
Google 官方持续更新,社区活跃度高,文档齐全,资源丰富。
-
-
本文档的目标和读者定位
文档目标
本系列文档旨在从零开始,系统性讲解 Flutter 框架的核心概念与开发实战内容。通过理论与实操结合,帮助读者完成从入门到进阶的技能成长路径。
具体目标包括:
-
理解 Flutter 的核心组件与布局体系
-
能够独立开发一个简单完整的 Flutter 应用
-
掌握跨平台适配、状态管理等实用技能
-
2. 环境准备
2.1 安装 Android Studio
-
下载地址与版本选择
官网地址:(最好开VPN)访问 developer.android.com/studio 或者 Android Studio 下载文件归档 | Android Developers
-
Android Studio 简单介绍
Android Studio 是 Google 官方推出的 Android 应用开发集成环境(IDE),基于 JetBrains 的 IntelliJ IDEA 平台构建。它是开发 Android 原生应用和 Flutter 应用的推荐工具,提供了丰富的功能来帮助开发者高效编写、调试和测试应用程序, Android Studio 是一个功能齐全、插件丰富的现代化开发环境,不仅适用于传统 Android 开发,也是目前 Flutter 开发的首选 IDE。无论是新手学习,还是企业级项目开发,Android Studio 都提供了良好的开发支持与工具生态
2.2 安装 Flutter SDK
-
Flutter SDK 下载与安装步骤(Windows)
官方地址:Archive | Flutter
-
设置环境变量
-
在系统环境变量中新建变量
变量名:PUB_HOSTED_URL 变量值:https://pub.flutter-io.cn
变量名:FLUTTER_STORAGE_BASE_URL 变量值:https://storage.flutter-io.cn
-
在系统变量 PATH 中添加 Flutter bin目录
D:\flutter_windows_3.24.1-stable\flutter\bin
-
Android Studio 下载 SDK 工具和 Android SDK Comman-line Tools 并下载 Flutter 和 Dart 插件
-
执行命令
flutter doctor -v
首次执行 Flutter 命令会从网络中拉取 Dart SDK、flutter工具等,这个过程会比较漫长
可能一直卡在
C:\Users\zengjh1>D:\flutter_windows_3.22.1-stable\flutter\bin\flutter.bat doctor
Checking Dart SDK version…
Downloading Dart SDK from Flutter engine …只能耐心等待,或者关闭重来,下载完后会显示 flutter 结果
[√] Flutter (Channel stable, 3.24.1, on Microsoft Windows [版本 10.0.19044.5737], locale zh-CN)• Flutter version 3.24.1 on channel stable at D:\flutter_windows_3.24.1-stable\flutter• Upstream repository https://github.com/flutter/flutter.git• Framework revision 5874a72aa4 (11 months ago), 2024-08-20 16:46:00 -0500• Engine revision c9b9d5780d• Dart version 3.5.1• DevTools version 2.37.2• Pub download mirror https://pub.flutter-io.cn• Flutter download mirror https://storage.flutter-io.cn[√] Windows Version (Installed version of Windows is version 10 or higher)[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0)• Android SDK at D:\SDK• Platform android-35, build-tools 35.0.0• ANDROID_SDK_ROOT = D:\SDK• Java binary at: C:\Program Files\Java\jdk-17\bin\java• Java version Java(TM) SE Runtime Environment (build 17+35-LTS-2724)X Android license status unknown.Run `flutter doctor --android-licenses` to accept the SDK licenses.See https://flutter.dev/to/windows-android-setup for more details.[√] Chrome - develop for the web• Chrome at C:\Users\zengjh1\AppData\Local\Google\Chrome\Application\chrome.exe[X] Visual Studio - develop Windows appsX Visual Studio not installed; this is necessary to develop Windows apps.Download at https://visualstudio.microsoft.com/downloads/.Please install the "Desktop development with C++" workload, including all of its default components[√] Android Studio (version 2024.3)• Android Studio at F:\Program Files\Android\Android Studio• Flutter plugin can be installed from:https://plugins.jetbrains.com/plugin/9212-flutter• Dart plugin can be installed from:https://plugins.jetbrains.com/plugin/6351-dart• Java version OpenJDK Runtime Environment (build 21.0.6+-13355223-b631.42)[√] Connected device (3 available)• Windows (desktop) • windows • windows-x64 • Microsoft Windows [版本 10.0.19044.5737]• Chrome (web) • chrome • web-javascript • Google Chrome 117.0.5938.63• Edge (web) • edge • web-javascript • Microsoft Edge 138.0.3351.65[√] Network resources• All expected network resources are available.! Doctor found issues in 2 categories.
会提示我们那些工具缺少了什么,我们用的是 AndroidStudio,所以只要保证 AndroidStudio 这一栏没问题就行
-
2.3 安装 Dart 插件和 Flutter 插件
-
在 Android Studio 中安装插件的方法
在 File -> Setting -> Plugins -> Marketplace 下搜索 Dart 和 Flutter 插件下载安装即可。
2.4 连接真实设备
- 设备开启开发者 USB 调试模式
- 设备连接与调试授权
3. 创建第一个 Flutter 项目
3.1 通过 Android Studio 创建 Flutter 项目
-
选择 Flutter 项目
-
配置 Flutter SDK path
-
项目配置
3.2 项目结构介绍
-
lib/
文件夹及主要 Dart 文件-
lib/
是 Dart 代码的主目录 -
main.dart
是应用的启动文件,负责引导整个 UI 构建。 -
项目结构建议按模块划分(如
pages/
、widgets/
等),便于组织和维护。
-
-
pubspec.yaml
文件含义pubspec.yaml
是 Flutter 和 Dart 项目的配置文件,用于声明项目的依赖、资源、版本信息、打包配置等内容。它类似于其他语言生态的配置文件,例如:
-
Node.js 的
package.json
-
Java 的
pom.xml
-
Python 的
requirements.txt
项目 功能描述 name
,version
定义项目元信息 dependencies
项目运行所需依赖 dev_dependencies
测试/开发所需依赖 flutter/assets
声明项目使用的图片、JSON、音频等资源 flutter/fonts
配置自定义字体 uses-material-design
是否使用 Material 风格设计 -
4. 编写第一个 Flutter 界面
4.1 了解 Widget 体系
-
StatelessWidget 和 StatefulWidget 区别
-
StatelessWidget(无状态组件)
StatelessWidget
是 不可变的 ,其构建内容在生命周期中不会发生变化。适用场景:
-
内容不需要更新,比如固定文本、图标、样式按钮等。
-
UI 仅依赖构造时传入的数据。
class HelloText extends StatelessWidget {final String name;const HelloText({super.key, required this.name}); Widget build(BuildContext context) {return Text('Hello, $name');} }
-
-
StatefulWidget(有状态组件)
StatefulWidget
是 可变的 ,拥有自己的状态对象State
,当状态改变时会触发 UI 重新构建 (setState()
)。适用场景:
-
UI 需要根据用户交互或数据更新而改变
-
比如按钮点击计数、输入框内容、动画等。
class CounterWidget extends StatefulWidget {const CounterWidget({super.key}); State<CounterWidget> createState() => _CounterWidgetState(); }class _CounterWidgetState extends State<CounterWidget> {int _count = 0;void _increment() {setState(() {_count++;});} Widget build(BuildContext context) {return Column(children: [Text('Count: $_count'),ElevatedButton(onPressed: _increment, child: const Text('Increment')),],);} }
-
区别总结
特性 StatelessWidget StatefulWidget 状态是否可变 否(不可变) 是(可变) 是否持有状态对象 否 是(通过 State 类) UI 是否可动态更新 否 是(调用 setState()
)重建方式 构造函数参数变化时重建 setState()
调用后重建常见应用场景 静态文本、图标、按钮等 表单输入、计数器、动画等 -
-
Widget 树的概念
在 Flutter 中,一切都是 Widget,页面 UI 是由各种 Widget 通过嵌套组合而成的,这种嵌套结构被称为 Widget 树
-
什么是 Widget 树
Widget 树是指:一个页面上的所有元素(按钮、文字、图片、容器等)以”树“的结构从上到下排列组合而成。
每一个 Widget 都可能包含子 Widget,它们像”树枝”一样组成整个页面的布局和逻辑
MaterialApp └── Scaffold├── AppBar└── Body└── Column├── Text└── ElevatedButton
-
Widget 树的层级关系
-
父 Widget:包含其他 Widget(容器、布局等)
-
子 Widget:被包含在某个父 Widget 中
-
Flutter 会从上往下递归构建、渲染、更新整课 Widget 树
-
-
为什么理解 Widget 树很重要?
-
调试和布局排查:Widget 树帮助你理解某个组件在页面中的层级与位置;
-
性能优化:可以判断哪些 Widget 频繁重建,是否可以抽离为 Stateless;
-
构建思想转变:传统 UI 框架强调“修改视图”,Flutter 强调“重建 Widget 树”。
-
-
Widget 树的可视化工具
Flutter 提供了调试工具:
-
Flutter Inspector
(在 Android Studio、VSCode 中可用) -
可以查看实际 Widget 树结构,帮助开发者理解页面构造
-
-
-
总结
概念 说明 StatelessWidget
不可变组件,适合静态展示,构建后不会改变 StatefulWidget
可变组件,内部状态变化时可使用 setState()
触发重建Widget 树 所有 Widget 按嵌套结构组成的一棵树,构成 UI 的骨架
4.2 修改默认代码为“Hello World”
-
替换原先
main.dart
内容为import 'package:flutter/material.dart';void main() => runApp(const MyApp());class MyApp extends StatelessWidget {const MyApp(); Widget build(BuildContext context) {return const MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {const HelloWorldPage(); Widget build(BuildContext context) {return const Scaffold(body: Center(child: Text('Hello World',style: TextStyle(fontSize: 24),),),);} }
5. Flutter 组件详解
5.1 基础组件
-
Text(文本显示)
用于在界面中显示一段文本
Text('Hello Flutter')
常用属性:
属性名 类型 说明 style
TextStyle
设置字体大小、颜色、粗细、行高等 textAlign
TextAlign
文本对齐方式(如 center
、left
)maxLines
int
显示的最大行数 overflow
TextOverflow
文本超出时的处理(如 ellipsis
)示例
Text('欢迎学习 Flutter!',style: TextStyle(fontSize: 20,color: Colors.blue,fontWeight: FontWeight.bold),textAlign: TextAlign.center,maxLines: 1,overflow: TextOverflow.ellipsis,)
-
Image(图片)
用于显示本地或网络图片
常用构造函数:
函数名 说明 Image.asset()
加载项目中的本地图片 Image.network()
加载网络图片 Image.file()
加载本地文件系统中的图片 Image.memory()
加载内存中的图片 示例
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Scaffold(body: Center(child: Image.network('https://img.shetu66.com/zt/1661475606815_a10229ff.jpg',width: 200,height: 80,),),);} }
-
Icon(图标)
用于显示 Material Design 风格的图标
基本用法
Icon(Icons.home)
常用属性
属性名 说明 Icons.xxx
图标名,Flutter 内置许多图标 size
图标大小 color
图标颜色 示例
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Scaffold(body: Center(child: Icon(Icons.favorite,color: Colors.red,size: 32,),),);} }
对比
组件 | 用途 | 典型构造方法 | 常用属性 |
---|---|---|---|
Text | 显示文字 | Text('xxx') | style , textAlign |
Image | 显示图片 | Image.asset() , Image.network() | width , height , fit |
Icon | 显示图标 | Icon(Icons.xxx) | size , color |
5.2 布局组件
-
Container(容器)
Container
是一个组合型的组件(组合了尺寸、边距、填充、对齐、颜色、装饰、变换等功能)。它本身不渲染任何内容,但可以承载一个子 Widget,并通过属性来控制它的展示方式,它相当于
HTML 中的
<div>
+ CSS 中的 margin/padding/background/transform 组合体。常用属性
属性 类型 说明 child
Widget 子组件 width
/height
double 设置容器的宽度和高度 margin
EdgeInsets
外边距 padding
EdgeInsets
内边距(对子组件生效) color
Color 背景颜色(不能与 decoration.color
同时使用)alignment
Alignment
控制子组件在容器内的位置 decoration
BoxDecoration
背景装饰(如圆角、边框、背景图等) transform
Matrix4
容器的几何变换(如旋转、缩放、平移) 示例
-
设置宽高 + 背景色 + 子组件居中
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Container(width: 200,height: 100,color: Colors.blue,alignment: Alignment.center,child:const Text('Hello Container', style: TextStyle(color: Colors.white)),);} }
-
设置内边距和外边距
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Container(margin: const EdgeInsets.all(16),padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),color: Colors.green,child: const Text('带边距的文本'),);} }
-
-
使用装饰
decoration
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Container(width: 150,height: 150,decoration: BoxDecoration(color: Colors.orange,borderRadius: BorderRadius.circular(16),border: Border.all(color: Colors.black, width: 2),),child: const Center(child: Text('装饰效果')),);} }
-
添加变换(旋转)
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {MyApp(); Widget build(BuildContext context) {return MaterialApp(home: HelloWorldPage(),);} }class HelloWorldPage extends StatelessWidget {HelloWorldPage(); Widget build(BuildContext context) {return Container(width: 100,height: 100,color: Colors.purple,transform: Matrix4.rotationZ(0.2),alignment: Alignment.center,child: const Text('旋转'),);} }
-
Padding(内边距)
Padding
是 Flutter 中用于给子组件添加 内边距(padding) 的布局组件。
它的作用是:在子组件的外部(但在边框内部)增加空白区域。语法结构
Padding(padding: EdgeInsets.all(8.0), // 设置内边距child: Text('Hello Padding'), )
示例
-
四边统一内边距
Padding(padding: EdgeInsets.all(16),child: Text('我有 16 的内边距'), )
-
水平、垂直内边距不同
Padding(padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),child: Text('左右 24,上下 12'), )
-
仅指定某个方向
Padding(padding: EdgeInsets.only(top: 20, left: 10),child: Text('仅上边距 20,左边距 10'), )
Padding
与Container
的区别特性 Padding
Container
设置内边距 专门用于设置内边距 (但只是组合属性的一部分) 设置颜色、大小 不支持 可以设置宽高、颜色、装饰等 推荐场景 专注间距控制 通用容器,做样式和布局控制更全面 -
Align(对齐)
Align
是 Flutter 中用于 对子组件进行位置控制 的组件。它会在自身范围内,将child
放置到指定的位置(例如居中、左上、右下等)基本语法
Align(alignment: Alignment.center, // 默认值child: Text('居中显示') )
alignment 属性详解
常量 对应位置 Alignment.topLeft
左上角 Alignment.topCenter
上中 Alignment.topRight
右上角 Alignment.centerLeft
左中 Alignment.center
中间(默认) Alignment.centerRight
右中 Alignment.bottomLeft
左下角 Alignment.bottomCenter
下中 Alignment.bottomRight
右下角 本质上,
alignment
是一个二维坐标系:- ”
(-1, -1)
表示左上角,(1,1)
表示右下角,(0, 0)
表示正中间。“
示例
-
文字显示在右下角
Align(alignment: Alignment.bottomRight,child: Text('右下角文字'), )
-
放一张图片到左上角
Align(alignment: Alignment.topLeft,child: Image.asset('assets/images/avatar.png', width: 60), )
-
附加属性
widthFactor
和heightFactor
这些属性可以影响 Align 本身的大小
-
widthFactor
:子组件宽度 × 倍数,作为 Align 的宽度; -
heightFactor
:子组件高度 × 倍数,作为 Align 的高度;
Align(alignment: Alignment.center,widthFactor: 2,heightFactor: 2,child: Text('我是 2 倍大'),)
-
-
和其他对齐组件的区别
组件 功能描述 Align
精确控制子组件在父组件中的位置 Center
相当于 Align(alignment: Alignment.center)
Padding
设置内边距,但不能控制子组件的具体位置 Positioned
用于 Stack
中,绝对定位
- ”
-
Center(居中)
Center
是一个非常简单的布局组件,它的作用是:将子组件放在父容器的中心位置基本语法
Center(child: Text('居中显示'), )
它会自动让
Text
或其他子组件在父容器中 水平居中 + 垂直居中示例
-
居中显示文本
Center(child: Text('Hello Center',style: TextStyle(fontSize: 24),), )
-
居中显示图片
Center(child: Image.asset('assets/images/logo.png', width: 100), )
-
结合
Container
使用Container(width: 300,height: 300,color: Colors.blue.shade100,child: Center(child: Text('我是居中的文字'),), )
-
Center
和其他布局组件的区别组件 用途 特点 Center
子组件居中 最简单,等价于 Align.center
Align
子组件任意对齐 更灵活,需要手动指定 alignment
Padding
增加空白区域,但不控制对齐方式 Positioned
Stack
中做绝对定位需要配合 Stack
使用
-
-
Row(水平排列)
Row
是一个横向布局组件,用于 将多个组件水平排列在一行内基本语法
Row(children: [Text('A'),Text('B'),Text('C'),], )
这段代码会将
A B C
横向排在一行里。-
常用属性详情
属性名 类型 说明 children
List<Widget>
子组件列表 mainAxisAlignment
MainAxisAlignment
主轴(水平方向)对齐方式 crossAxisAlignment
CrossAxisAlignment
交叉轴(垂直方向)对齐方式 mainAxisSize
MainAxisSize
主轴尺寸:最大/最小(是否占满可用空间) textDirection
TextDirection
布局方向:从左到右(默认)还是从右到左 -
mainAxisAlignment
对齐选项(水平)属性 效果 MainAxisAlignment.start
左对齐(默认) MainAxisAlignment.center
水平居中 MainAxisAlignment.end
右对齐 MainAxisAlignment.spaceBetween
两端对齐,子项平均分布 MainAxisAlignment.spaceAround
子项周围空白相等 MainAxisAlignment.spaceEvenly
子项之间空白完全相等 示例
Row(mainAxisAlignment: MainAxisAlignment.center,children: const [Icon(Icons.star, color: Colors.red),Icon(Icons.star_border, color: Colors.red),Icon(Icons.star_half, color: Colors.red),],)
-
crossAxisAlignment
对齐选项(垂直)属性 效果 CrossAxisAlignment.start
顶部对齐 CrossAxisAlignment.center
垂直居中(默认) CrossAxisAlignment.end
底部对齐 CrossAxisAlignment.stretch
拉伸子项填满垂直空间 baseline
(需设置 textBaseline)按文本基线对齐
-
-
Column(垂直排列)
Column
是一个 竖直方向布局组件 ,可以让多个子组件 从上到下一次排列基本语法
Column(children: [Text('第一行'),Text('第二行'),Text('第三行'),], )
-
常用属性解释
属性名 类型 说明 children
List<Widget>
子组件列表 mainAxisAlignment
MainAxisAlignment
主轴(竖直方向)对齐方式 crossAxisAlignment
CrossAxisAlignment
交叉轴(水平方向)对齐方式 mainAxisSize
MainAxisSize
主轴大小控制(是否占满可用垂直空间) -
主轴对齐(mainAxisAlignment)
控制子组件在竖直方向上的排列方式:
属性值 效果 MainAxisAlignment.start
从顶部开始(默认) MainAxisAlignment.center
垂直居中 MainAxisAlignment.end
底部对齐 MainAxisAlignment.spaceBetween
上下贴边,中间平均分布 MainAxisAlignment.spaceAround
每个子组件周围间距相等 MainAxisAlignment.spaceEvenly
所有子组件间距完全相等 -
交叉轴对齐(crossAxisAlignment)
控制子组件在水平方向上的对齐方式
属性值 效果 CrossAxisAlignment.start
左对齐(默认) CrossAxisAlignment.center
水平居中 CrossAxisAlignment.end
右对齐 CrossAxisAlignment.stretch
拉伸子组件到最大宽度
示例
-
简单垂直排布
Column(mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: const [Text('标题'),SizedBox(height: 10),Text('副标题'),SizedBox(height: 10),Icon(Icons.star, size: 32),],)
-
加背景 + 居中演示(配合 Container)
Container(width: double.infinity,height: 300,color: Colors.blue.shade50,child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly,crossAxisAlignment: CrossAxisAlignment.center,children: const [Text('上'),Text('中'),Text('下'),],),)
-
-
Stack(层叠布局)
Stack
是一个 堆叠布局组件 允许多个子组件 按照 z 轴 (前后)方向叠加在一起基本语法
Stack(children: [Container(width: 200, height: 200, color: Colors.blue),Positioned(top: 20,left: 20,child: Icon(Icons.star, size: 50, color: Colors.white),),], )
-
常用属性解释
属性名 类型 说明 children
List<Widget>
所有子组件,越靠后越在上层 alignment
Alignment
控制非 Positioned 子组件的位置 fit
StackFit
控制子组件尺寸如何适应 Stack clipBehavior
Clip
是否裁剪超出部分(默认 Clip.hardEdge
) -
Stack
vsPositioned
-
Stack
用来定义多个叠加的层 -
Positioned
用来对某个子组件进行绝定位
和基本语法示例对比
Stack(children: [Container(color: Colors.yellow, width: 200, height: 200),Positioned(bottom: 10,right: 10,child: Text('右下角'),),], )
-
-
alignment:对非 Positioned 的子组件对齐
Stack(alignment: Alignment.center,children: [Container(width: 100, height: 100, color: Colors.red),Text('居中'), // 自动居中],)
-
5.3 按钮和交互组neiElevatedButton / TextButton / OutlinedButton(各种按钮)
-
ElevatedButton / TextButton / OutlinedButton(各种按钮)
按钮类型 外观描述 适用场景 ElevatedButton
有阴影、背景填充、立体感强 用于强调操作,如“提交” TextButton
无边框、无背景,仅文本 用于辅助操作、二级选项 OutlinedButton
有边框但无背景 用于不那么主要的操作按钮 -
ElevatedButton
立体按钮Container(child: Column(children: [ElevatedButton(onPressed: () {print('点击了 ElevatedButton');},child: Text('确定'),)],),color: Colors.white,)
常用于强调主要操作,例如 “登录”、“提交”。
-
TextButton
(纯文本按钮)TextButton(onPressed: () {print('点击了 TextButton');},child: Text('取消'),)
用于不那么显眼的按钮,比如“忘记密码”、“查看更多”。
-
OutlinedButton
(带边框按钮)OutlinedButton(onPressed: () {print('点击了 OutlinedButton');},child: Text('边框按钮'), )
用于中性操作,比如“跳过”、“稍后再说”。
-
自定义按钮样式
三种按钮都支持使用
style
参数来自定义外观,使用ButtonStyle
类ElevatedButton(onPressed: () {},style: ElevatedButton.styleFrom(primary: Colors.blue, // 背景色onPrimary: Colors.white, // 文字颜色padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),),),child: Text('自定义样式'), )
-
使用场景建议
场景 推荐按钮类型 提交、主操作 ElevatedButton
取消、跳过、轻操作 TextButton
次要但需强调(边界操作) OutlinedButton
图标 + 文本按钮 *.icon()
系列
-
-
GestureDetector(手势识别)
GestureDetector
是一个 手势识别器 可以监听用户在屏幕上的各种操作(手势)如-
点击(Tap)
-
双机(Double Tap)
-
长按(Long Press)
-
拖动(Drag)
-
缩放(Scale)
基本语法
GestureDetector(onTap: () {print('点击了组件');},child: Container(color: Colors.blue,padding: EdgeInsets.all(20),child: Text('点我'),), )
-
常用事件一览
属性名 类型 说明 onTap
void Function()
单击 onDoubleTap
void Function()
双击 onLongPress
void Function()
长按 onPanUpdate
Function(DragUpdateDetails)
拖动时触发(全向) onPanStart
/onPanEnd
- 拖动开始 / 结束 onScaleUpdate
Function(ScaleUpdateDetails)
双指缩放
示例
-
点击、长按、双击事件
GestureDetector(onTap: () => print('点击'),onDoubleTap: () => print('双击'),onLongPress: () => print('长按'),child: Container(padding: EdgeInsets.all(20),color: Colors.lightGreen,child: Text('点我试试'),), )
-
拖动(onPanUpdate)
GestureDetector(onPanUpdate: (details) {print('dx: ${details.delta.dx}, dy: ${details.delta.dy}');},child: Container(width: 200,height: 200,color: Colors.orange,child: Center(child: Text('拖动我')),), )
-
缩放(onScaleUpdate)
GestureDetector(onScaleUpdate: (details) {print('缩放比例:${details.scale}');},child: Image.asset('assets/images/logo.png'), )
总结
-
功能 | 是否支持 | 示例属性 |
---|---|---|
点击 | 支持 | onTap |
双击 | 支持 | onDoubleTap |
长按 | 支持 | onLongPress |
拖动 | 支持 | onPanUpdate |
缩放 | 支持 | onScaleUpdate |
支持嵌套其他组件 | 支持 | child |
无视觉效果(非按钮) | 支持 | 需要自定义样式 |
-
InkWell(水波纹效果点击)
InkWell
是一个 带水波纹(涟漪)点击效果的手势识别组件。 相比GestureDetector
它有更好的 Material 设计风格的视觉效果它属于 Material 组件体系的一部分,使用时需要有
Material
组件作为“水波纹的绘制容器”基本用法
InkWell(onTap: () {print('点击了 InkWell');},child: Padding(padding: EdgeInsets.all(16),child: Text('点我'),), )
点击时会看到水波纹从点击点扩散开来
-
常用属性
属性名 类型 说明 onTap
void Function()?
点击事件 onDoubleTap
void Function()?
双击事件 onLongPress
void Function()?
长按事件 borderRadius
BorderRadius
设置水波纹圆角 splashColor
Color
设置水波纹颜色 highlightColor
Color
按下时的背景色 child
Widget
显示内容 -
配合
Material
使用 (必须)Material(color: Colors.blue[50],borderRadius: BorderRadius.circular(12),child: InkWell(onTap: () {print('点到了卡片');},borderRadius: BorderRadius.circular(12),splashColor: Colors.redAccent.withOpacity(0.2),child: Padding(padding: EdgeInsets.all(20),child: Text('有点击水波纹的卡片'),),),)
-
和
GestureDetectro
区别对比对比点 GestureDetector
InkWell
是否有视觉反馈 无水波纹 有水波纹 是否依赖 Material
不依赖 必须依赖 Material 父组件 支持的手势种类 拖动、缩放、滑动等更丰富 主要用于点击相关 使用场景 自定义复杂交互 通常用于按钮、卡片、列表点击反馈等
-
5.4 输入框和表单
-
TextField(文本输入)
TextField
是最常用的文本输入组件,用于实现表单的输入、搜索框、聊天框等各种输入功能基本用法
TextField(decoration: InputDecoration(labelText: '用户名',hintText: '请输入用户名',border: OutlineInputBorder(),), )
效果:一个带标签、提示文字、边框的输入框
-
常用属性详情
属性名 类型 说明 controller
TextEditingController
控制和监听输入框内容 decoration
InputDecoration
装饰输入框(如提示、图标、边框等) obscureText
bool
是否隐藏输入内容(用于密码) keyboardType
TextInputType
输入类型(文本、数字、邮箱等) maxLines
int
输入框最大行数 onChanged
Function(String)
文本改变时回调 onSubmitted
Function(String)
用户按下“完成/提交”时的回调 enabled
bool
是否可编辑 readOnly
bool
是否只读
示例
-
带控制器示例(获取输入内容)
class TextFieldExample extends StatelessWidget {final TextEditingController _controller = TextEditingController(); Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('TextField 示例')),body: Padding(padding: const EdgeInsets.all(16.0),child: Column(children: [TextField(controller: _controller,decoration: InputDecoration(labelText: '输入内容'),),SizedBox(height: 20),ElevatedButton(onPressed: () {print("你输入了: ${_controller.text}");},child: Text('提交'))],),),);} }
-
密码框(隐藏输入)
TextField(obscureText: true,decoration: InputDecoration(labelText: '密码',border: OutlineInputBorder(),),)
不同输入类型
输入类型 示例设置 文本(默认) keyboardType: TextInputType.text
数字 keyboardType: TextInputType.number
电话 keyboardType: TextInputType.phone
邮箱 keyboardType: TextInputType.emailAddress
-
多行输入
TextField(maxLines: 5,decoration: InputDecoration(labelText: '多行备注'), )
-
自定义装饰 InputDecoration 示例
TextField(decoration: InputDecoration(prefixIcon: Icon(Icons.person),suffixIcon: Icon(Icons.clear),labelText: '用户名',hintText: '请输入用户名',border: OutlineInputBorder(),), )
-
-
Checkbox(多选框)
Checkbox
是一个可以勾选/取消的组件,只有两个状态(true
/false
) 可以搭配文字或图标一起使用。基本用法
bool _isChecked = false;Checkbox(value: _isChecked,onChanged: (bool? value) {setState(() {_isChecked = value!;});}, )
必须在
StatefulWidget
中使用,因为复选框的值需要动态更新。示例
class CheckBoxDemo extends StatefulWidget { _CheckBoxDemoState createState() => _CheckBoxDemoState(); }class _CheckBoxDemoState extends State<CheckBoxDemo> {bool _isSelected = false; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Checkbox 示例")),body: Center(child: Row(mainAxisSize: MainAxisSize.min,children: [Checkbox(value: _isSelected,onChanged: (bool? value) {setState(() {_isSelected = value!;});},),Text(_isSelected ? "已选中" : "未选中"),],),),);} }
常用属性
属性名 类型 说明 value
bool
当前是否勾选 onChanged
(bool?) → void
勾选状态变化时的回调函数 activeColor
Color
选中时的颜色 checkColor
Color
号颜色 tristate
bool
是否支持三种状态(true/false/null) 搭配
CheckboxListTitle
(复选框 + 标题 + 子标题)CheckboxListTile(title: Text("我同意协议"),subtitle: Text("点击确认后继续"),value: _isChecked,onChanged: (value) {setState(() {_isChecked = value!;});},secondary: Icon(Icons.policy),controlAffinity: ListTileControlAffinity.leading,)
总结
你想实现的功能 使用方式或属性 基本复选框 Checkbox
复选框 + 文字 Row + Text
或CheckboxListTile
支持不确定(null)状态 tristate: true
更好看的样式和布局 用 CheckboxListTile
-
Radio(单选框)
Radio<T>
是 Flutter 提供的泛型组件,用于在多个选项中选择一个,必须搭配groupValue
一起使用。最基本的用法示例
Radio<int>(value: 1,groupValue: _selectedValue,onChanged: (int? value) {setState(() {_selectedValue = value!;});}, )
-
value
:表示当前这个单选按钮的值 -
groupValue
:表示当前“选中的值” -
onChanged
:当点击时调用,传入的就是value
选择性别示例:
class RadioDemo extends StatefulWidget { _RadioDemoState createState() => _RadioDemoState(); }class _RadioDemoState extends State<RadioDemo> {String _gender = "男"; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Radio 示例")),body: Column(children: [ListTile(title: Text("男"),leading: Radio<String>(value: "男",groupValue: _gender,onChanged: (value) {setState(() {_gender = value!;});},),),ListTile(title: Text("女"),leading: Radio<String>(value: "女",groupValue: _gender,onChanged: (value) {setState(() {_gender = value!;});},),),SizedBox(height: 20),Text("你选择的是:$_gender"),],),);} }
常用属性一览
属性名 类型 说明 value
T
当前这个选项的值 groupValue
T
当前组中被选中的值 onChanged
Function(T?)
点击时回调 activeColor
Color
选中状态颜色 toggleable
bool
是否支持再次点击取消(Flutter 3.7+) -
-
Switch(开关)
Switch
是 Flutter 提供的滑动切换组件,只有两个状态:true
(开启)和false
(关闭)最基本的用法
bool _isOn = false;Switch(value: _isOn,onChanged: (bool value) {setState(() {_isOn = value;});}, )
必须在
StatefulWidget
中使用,因为开关状态需要实时更新。示例:
-
控制某功能开关
class SwitchDemo extends StatefulWidget { _SwitchDemoState createState() => _SwitchDemoState(); }class _SwitchDemoState extends State<SwitchDemo> {bool _isDarkMode = false; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Switch 示例")),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Switch(value: _isDarkMode,onChanged: (bool value) {setState(() {_isDarkMode = value;});},),Text(_isDarkMode ? '暗黑模式已开启' : '暗黑模式已关闭'),],),);} }
常用属性
属性名 类型 说明 value
bool
当前开关状态 onChanged
(bool) → void
状态变化回调函数 activeColor
Color
开启时的主色(圆点颜色) activeTrackColor
Color
开启时轨道颜色 inactiveThumbColor
Color
关闭时圆点颜色 inactiveTrackColor
Color
关闭时轨道颜色 materialTapTargetSize
MaterialTapTargetSize
调整点击区域大小 -
-
Form 与 FormField(表单管理)
在 Flutter 中,
Form
和FormField
是用于统一管理多个输入组件的表单系统,可以方便地进行表单验证、提交等操作,常用于登录、注册、反馈等界面。-
什么是
Form
和FormField
组件 作用说明 Form
表单容器,用于管理一组输入项(字段) FormField
表单字段的基类(如 TextFormField) TextFormField
是最常用的FormField
实现,是带表单验证功能的输入框 -
Form
的基本结构final _formKey = GlobalKey<FormState>();Form(key: _formKey,child: Column(children: [TextFormField(decoration: InputDecoration(labelText: '用户名'),validator: (value) {if (value == null || value.isEmpty) {return '请输入用户名';}return null;},),ElevatedButton(onPressed: () {if (_formKey.currentState!.validate()) {// 所有字段验证通过print('验证成功,提交数据');}},child: Text('提交'),),],), )
-
关键知识点说明
项目 说明 FormState
表单状态对象,管理字段验证、保存等操作 GlobalKey<FormState>
唯一标识表单,获取 FormState
对象validate()
执行所有字段的 validator
方法,返回是否通过验证save()
触发每个字段的 onSaved
回调(如果设置)reset()
重置所有字段内容和状态 -
完整示例
class FormExample extends StatefulWidget { _FormExampleState createState() => _FormExampleState(); }class _FormExampleState extends State<FormExample> {final _formKey = GlobalKey<FormState>();String _username = '';String _password = ''; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Form 表单示例')),body: Padding(padding: EdgeInsets.all(16),child: Form(key: _formKey,child: Column(children: [TextFormField(decoration: InputDecoration(labelText: '用户名'),validator: (value) {if (value == null || value.isEmpty) {return '请输入用户名';}return null;},onSaved: (value) {_username = value!;},),TextFormField(decoration: InputDecoration(labelText: '密码'),obscureText: true,validator: (value) {if (value == null || value.length < 6) {return '密码不能少于6位';}return null;},onSaved: (value) {_password = value!;},),SizedBox(height: 20),ElevatedButton(onPressed: () {if (_formKey.currentState!.validate()) {_formKey.currentState!.save();print('用户名: $_username');print('密码: $_password');}},child: Text('提交'),),],),),),);} }
-
TextField
VSTextFormField
区别项 TextField
TextFormField
表单验证支持 无验证方法 支持 validator/onSaved 等 与 Form 配合使用 需要单独管理状态 可统一使用 Form 管理 推荐使用场景 简单输入框 表单场景(如登录、注册等) -
一些常用方法(FormState)
方法名 说明 validate()
所有字段验证,返回布尔值 save()
调用每个字段的 onSaved()
reset()
重置整个表单
-
5.5 滚动视图
-
ListView(列表)
ListView
是一个 可滚动的线性列表视图组件 可以直接或水平显示一系列子组件-
最基本的用法
ListView(children: [ListTile(title: Text('第1项')),ListTile(title: Text('第2项')),ListTile(title: Text('第3项')),], )
默认是垂直方向的,超出屏幕会自动滚动。
-
常见构造方式
-
ListView
+children
: 静态少量内容 -
ListView.builder
: 动态列表(推荐) -
ListView.separated
: 带分隔线 -
ListView.custom
: 高级自定义构造(极少用)
-
-
常用属性
属性名 类型 说明 itemCount
int
列表项数量(用于 builder) itemBuilder
IndexedWidgetBuilder
构建每项内容的方法 scrollDirection
Axis
滚动方向( Axis.vertical
/horizontal
)reverse
bool
是否反转列表显示顺序 shrinkWrap
bool
是否根据内容自动收缩高度 physics
ScrollPhysics
滚动行为(如禁止、弹性等) padding
EdgeInsets
设置内边距 -
示例
class ListViewDemo extends StatelessWidget {final List<String> items = List.generate(20, (index) => '项目 $index'); Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('ListView 示例')),body: ListView.builder(itemCount: items.length,itemBuilder: (context, index) {return ListTile(leading: Icon(Icons.start),title: Text(items[index]),onTap: () {print('你点击了: ${items[index]}');},);}));} }
-
-
GridView(网格)
GridView
(网格布局),它是用来显示多列(多行多列)的组件,常用于图片展示、商品列表、图标宫格菜单等场景。GridView
是一个支持滚动的二维网格布局组件,和ListView
类似,但可以在横向上自动分布多个元素。-
常用构造方法
-
GridView.count
(常规固定列数网格)GridView.count(crossAxisCount: 3,children: List.generate(9, index {return Container(alignment: Alignment.center,color: Colors.blue[100 * ((index % 8) + 1)],child: Text('项 $index'));}); );
-
GridView.builder
(推荐用于大数据列表)GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, // 每行 2 个crossAxisSpacing: 10, // 横向间距mainAxisSpacing: 10, // 纵向间距childAspectRatio: 1.5, // 宽高比(默认是 1)),itemCount: 20,itemBuilder: (context, index) {return Container(color: Colors.teal[100 * ((index % 8) + 1)],alignment: Alignment.center,child: Text('Grid $index'),);}, )
-
GridView.extent
(指定最大宽度自动适配列数)GridView.extent(maxCrossAxisExtent: 100, // 每个项最大宽度,系统自动决定多少列children: List.generate(20, (index) {return Container(alignment: Alignment.center,color: Colors.orange[100 * ((index % 8) + 1)],child: Text('Item $index'),);}), )
-
-
常用属性说明
属性名 类型 说明 crossAxisCount
int
每行显示的列数 mainAxisSpacing
double
每行之间的间距(垂直方向) crossAxisSpacing
double
每列之间的间距(水平方向) childAspectRatio
double
宽高比(宽/高) shrinkWrap
bool
是否根据内容高度自适应(适用于嵌套) physics
ScrollPhysics
滚动行为(常用于嵌套时禁用滚动) -
示例
import 'package:flutter/material.dart';class GridViewExample extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('GridView 示例')),body: GridView.builder(padding: EdgeInsets.all(10),gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, // 3列crossAxisSpacing: 10,mainAxisSpacing: 10,childAspectRatio: 1.0, // 宽高比 1:1),itemCount: 12,itemBuilder: (context, index) {return Container(color: Colors.blue[100 * ((index % 8) + 1)],alignment: Alignment.center,child: Text('第 $index 项'),);},),);} }
-
-
SingleChildScrollView(单子节点滚动)
SingleChildScrollView
允许一个子组件在主轴滚动(通常是垂直) 适用于控件数量不定时避免溢出(overflow)错误。-
基本用法
SingleChildScrollView(child: Column(children: [Text('A'),Text('B'),Text('C'),// 很多内容...],), )
SingleChildScrollView
的child
只能是 一个 Widget,通常搭配Column
使用。 -
典型使用场景
-
登录页 / 注册页(键盘弹出时防止布局溢出)
-
表单页面(需要整体滚动)
-
多控件组合的页面(不是列表)
-
-
重要属性说明
属性名 类型 说明 scrollDirection
Axis
滚动方向,默认是 Axis.vertical
padding
EdgeInsets
内边距 reverse
bool
是否反向滚动 physics
ScrollPhysics
滚动行为(如弹性、不可滚动) controller
ScrollController
控制滚动、监听滚动位置等 -
示例
import 'package:flutter/material.dart';class ScrollDemo extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('SingleChildScrollView 示例')),body: SingleChildScrollView(padding: EdgeInsets.all(16),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: List.generate(20, (index) {return Padding(padding: EdgeInsets.symmetric(vertical: 8),child: Text('第 $index 行文本内容'));}),),),);} }
-
与
ListView
区别对比对比项 SingleChildScrollView
ListView
用法场景 多个固定控件、表单页面 长列表、动态项 性能优化 没有懒加载,所有内容一次性渲染 支持懒加载 子组件结构 一个 Widget(如 Column
)包多个控件多个 Widget 构建 嵌套使用 更适合嵌套在页面中或布局中 嵌套需注意高度限制和滚动冲突
-
5.6 导航和路由
-
Navigator 介绍
Navigator
是用于管理页面(Route)跳转和堆栈操作的组件,类似网页的前进、后退、跳转操作。-
什么是
Navigator
?Navigator
是一个页面堆栈管理器,你可以:-
push:打开新页面(入栈)
-
pop:返回上一个页面(出栈)
-
replace:替换当前页面
-
清空所有页面再跳转:跳转并清空历史
Navigator 通常配合
MaterialPageRoute
或named route
使用。 -
-
最基础的页面跳转方式
-
跳转到新页面(push)
Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()), );
-
返回上一级页面(pop)
Navigator.pop(context);
-
-
带返回值的页面跳转
A → B,B返回数据给A:
在 A 页面:
void _goToSecondPage() async {final result = await Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()),);print("从第二页返回的数据: $result"); }
在 B 页面:
ElevatedButton(onPressed: () {Navigator.pop(context, "这是返回值");},child: Text("返回并携带数据"), )
-
使用命名路由(推荐方式)
-
定义路由表
MaterialApp(initialRoute: '/',routes: {'/': (context) => HomePage(),'/second': (context) => SecondPage(),}, )
-
跳转方式
Navigator.pushNamed(context, '/second');
-
返回方式
Navigator.pop(context);
-
-
常见跳转方式对比
跳转方式 用法 适合场景 push()
直接传入 Widget 简单项目 pushNamed()
使用路由名称跳转 大型项目,统一管理路由 pushReplacement()
替换当前页面(无返回) 登录成功替换登录页等 pushAndRemoveUntil()
清空历史再跳转 登录后清空所有导航栈 -
小结
功能 推荐方式 普通页面跳转 Navigator.push()
命名路由跳转 Navigator.pushNamed()
页面返回携带数据 Navigator.pop(context, result)
替换页面,不保留返回 Navigator.pushReplacement()
清空页面栈并跳转 Navigator.pushAndRemoveUntil()
-
-
push 和 pop
push
和pop
是 Flutter 中Navigator
导航系统的两个最核心方法,分别用于打开新页面和返回上一个页面,就像“网页的前进和后退”。-
Navigator.push()
作用:** 打开(压栈)一个新页面**
Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()), );
-
context
:当前页面的上下文 -
MaterialPageRoute
:常用的页面过渡动画(安卓风格) -
SecondPage()
:你要跳转的新页面 Widget
示例
ElevatedButton(onPressed: () {Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()),);},child: Text("去第二页"), )
-
-
Navigator.pop()
作用:返回(出栈)上一个页面
Navigator.pop(context);
可选地返回一个值:
Navigator.pop(context, "返回的数据");
-
push
+pop
结合使用(带返回值)-
第一个页面
void _goToSecondPage() async {final result = await Navigator.push(context,MaterialPageRoute(builder: (context) => SecondPage()),);print("从第二页返回的数据是:$result"); }
-
第二个页面
ElevatedButton(onPressed: () {Navigator.pop(context, "你好,这是返回值");},child: Text("返回并传数据"), )
-
-
Navigator 的“堆栈”原理图示
初始: [ HomePage ]push(SecondPage) [ HomePage, SecondPage ]push(ThirdPage) [ HomePage, SecondPage, ThirdPage ]pop() [ HomePage, SecondPage ]
-
push / pop 常见变体
方法名 功能说明 push()
压入新页面 pop()
弹出当前页面 pushReplacement()
替换当前页面 popUntil()
返回到满足条件的页面 pushAndRemoveUntil()
清空页面栈并跳转 -
总结
功能 方法 打开新页面 Navigator.push()
返回上一页 Navigator.pop()
替换当前页面 Navigator.pushReplacement()
返回并带数据 Navigator.pop(context, value)
多页面返回(条件) Navigator.popUntil()
-
5.7 其他常用组件
-
AppBar(应用栏)
AppBar
是 Scaffold(脚手架页面)的顶部栏,常用于显示:页面标题(title)、返回按钮(自动生成)、操作按钮(Icon)、搜索框、TabBar、菜单等它是 Flutter 应用中几乎每个页面都会使用的标准导航栏。
-
基本语法
Scaffold(appBar: AppBar(title: Text('我是标题'),),body: Center(child: Text('内容')), )
-
常用属性说明
属性名 类型 作用说明 title
Widget
应用栏的标题,通常是 Text
leading
Widget
左侧图标(默认是返回箭头) actions
List<Widget>
右侧图标按钮列表 backgroundColor
Color
背景颜色 centerTitle
bool
是否居中标题(iOS 默认为 true) elevation
double
阴影高度(默认 4) bottom
PreferredSizeWidget
下方扩展区域,如 TabBar
-
示例
import 'package:flutter/material.dart';class AppBarExample extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('AppBar 示例'),leading: Icon(Icons.menu),actions: [IconButton(icon: Icon(Icons.search),onPressed: () {print('搜索按钮点击');},),IconButton(icon: Icon(Icons.more_vert),onPressed: () {print('更多菜单');},),],),body: Center(child: Text('页面内容区域'),),);} }
-
-
Scaffold(脚手架,基础页面布局)
Scaffold
是 Flutter 提供的 页面结构容器,提供了一个基本布局框架,包含:AppBar(顶部应用栏)、Body(主要内容区)、Drawer(侧边栏)、BottomNavigationBar(底部导航)、FloatingActionButton(悬浮按钮)、SnackBar(轻提示)等。它就像“页面的骨架”,你把各种 UI 部件放进去就可以构成完整的页面。
-
基本使用方式
Scaffold(appBar: AppBar(title: Text("首页")),body: Center(child: Text("Hello World")), )
-
Scaffold 的常用属性详解
属性名 类型 作用说明 appBar
AppBar
页面顶部导航栏 body
Widget
页面主要内容区域 floatingActionButton
FloatingActionButton
页面悬浮按钮 drawer
Drawer
左侧滑出菜单 bottomNavigationBar
BottomNavigationBar
页面底部导航栏 backgroundColor
Color
页面背景色 persistentFooterButtons
List<Widget>
固定在底部的按钮组 bottomSheet
Widget
页面底部悬浮层 -
示例
import 'package:flutter/material.dart';class ScaffoldExample extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Scaffold 示例')),body: Center(child: Text('我是页面内容')),floatingActionButton: FloatingActionButton(onPressed: () {ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("你点击了按钮")),);},child: Icon(Icons.add),),drawer: Drawer(child: ListView(children: [DrawerHeader(decoration: BoxDecoration(color: Colors.blue),child: Text("菜单头部", style: TextStyle(color: Colors.white))),ListTile(title: Text("选项1")),ListTile(title: Text("选项2"))],),),bottomNavigationBar: BottomAppBar(child: Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [IconButton(onPressed: (){}, icon: Icon(Icons.home)),IconButton(onPressed: (){}, icon: Icon(Icons.person))],),),);} }
-
常见组合搭配
页面需求 Scaffold 结构用法 普通页面(顶部+内容) appBar + body
带悬浮操作按钮 floatingActionButton
左侧菜单导航 drawer
底部固定菜单栏 bottomNavigationBar
orBottomAppBar
显示提示 ScaffoldMessenger.of(context).showSnackBar(...)
-
-
Drawer(抽屉导航)
Drawer
是 Scaffold 提供的一个侧边导航菜单,通常从左边滑出,用于展示导航选项、用户信息等。-
基本结构
Drawer(child: ListView(padding: EdgeInsets.zero,children: [DrawerHeader(decoration: BoxDecoration(color: Colors.blue),child: Text('用户信息'),),ListTile(leading: Icon(Icons.home),title: Text('首页'),onTap: () {// 点击事件},),ListTile(leading: Icon(Icons.settings),title: Text('设置'),onTap: () {// 点击事件},),],), )
-
Drawer 常用组件说明
组件 作用 DrawerHeader
抽屉顶部区域,一般用于展示用户头像、昵称 ListTile
列表项,一般用于菜单选项 ListView
内容可滚动 -
打开与关闭 Drawer
-
自动打开
用户手动左滑
点左上角菜单按钮(如果 AppBar 中设置了 automaticallyImplyLeading: true)
-
手动打开
Scaffold.of(context).openDrawer(); // 仅限于在子 Widget 中使用 Builder 包裹
-
手动关闭
Navigator.pop(context)
-
-
示例
class DrawerExample extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Drawer 示例')),drawer: Drawer(child: ListView(padding: EdgeInsets.zero,children: [const UserAccountsDrawerHeader(accountName: Text('张三'),accountEmail: Text("zhangsan@example.com"),currentAccountPicture: CircleAvatar(backgroundImage: AssetImage('assets/images/ic_launcher.png'),),),ListTile(leading: const Icon(Icons.home),title: const Text('首页'),onTap: () {Navigator.pop(context);},),ListTile(leading: const Icon(Icons.settings),title: const Text('设置'),onTap: () {Navigator.pop(context);},),],),),body: const Center(child: Text('主页面内容')));} }
-
小结
你要实现的功能 推荐做法 左侧菜单导航 使用 Scaffold.drawer
右侧快捷操作菜单 使用 Scaffold.endDrawer
展示用户头像信息 使用 UserAccountsDrawerHeader
菜单点击关闭并跳转 先 Navigator.pop()
再导航页面
-
-
BottomNavigationBar(底部导航栏)
BottomNavigationBar
是 Flutter 提供的一个底部导航栏组件,配合Scaffold
使用,支持多个标签切换视图页面。它可以 : 显示多个 tab 标签(一般 3 ~ 5 个);高亮当前选中项;点击切换页面(配合
IndexedStack
)-
基本用法
Scaffold(bottomNavigationBar: BottomNavigationBar(currentIndex: 0, // 当前选中索引onTap: (index) {// 切换页面逻辑},items: [BottomNavigationBarItem(icon: Icon(Icons.home),label: '首页',),BottomNavigationBarItem(icon: Icon(Icons.person),label: '我的',),],), )
-
示例
import 'package:flutter/material.dart';class BottomNavExample extends StatefulWidget { _BottomNavExampleState createState() => _BottomNavExampleState(); }class _BottomNavExampleState extends State<BottomNavExample> {int _currentIndex = 0;final List<Widget> _pages = [Center(child: Text('首页内容')),Center(child: Text('分类内容')),Center(child: Text('我的内容'))]; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("底部导航示例")),body: IndexedStack (index: _currentIndex,children: _pages,),bottomNavigationBar: BottomNavigationBar (currentIndex: _currentIndex,onTap: (index) {setState(() {_currentIndex = index;});},items: [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.person), label: "我的"),],),);} }
-
属性说明
属性名 类型 说明 items
List 菜单项(最少2项) currentIndex
int 当前选中项的索引 onTap
Function(int) 点击导航项回调 type
BottomNavigationBarType 显示样式: fixed
(默认)或shifting
(动效)selectedItemColor
Color 选中项颜色 unselectedItemColor
Color 未选中项颜色 backgroundColor
Color 背景色
-
6. 状态管理基础
6.1 什么是状态?
简单来说,状态就是某个变量的值 当这个值发生变化时,对应的 UI会自动刷新 展示新的内容,
比如:
-
一个计数器的数字是状态 (
count = 3
) -
一个按钮是否选中是状态(
isSelected = true
) -
一个页面当前是“加载中”还是“已完成”是状态(
loading = true / false
)
示例
int count = 0; // 这就是一个状态ElevatedButton(onPressed: () {setState(() {count++;});},child: Text('点击了 $count 次'),
)
-
Flutter 中状态是怎么驱动 UI 的?
Flutter 的 Widget 是声明时UI,它不是手动改动控件,而是重新构建:
// 当状态改变时 setState((){count++; // 修改状态 }); // Flutter 自动重新调用 build() -> 根据新状态更新 UI
这就是 Flutter 的核心机制: 状态驱动UI
-
状态在哪些 Widget 中存在?
Widget 类型 状态管理方式 StatelessWidget(无状态) 固定不变的 UI,只能显示数据 StatefulWidget(有状态) 可变 UI,状态变化会自动刷新 -
常见状态的例子
场景 状态变量 计数器 int counter
登录表单 String username
,password
切换主题 bool isDarkMode
是否选中某项 bool isChecked
当前页面索引 int currentIndex
7. 资源管理
-
图片资源的使用
在 Flutter 中使用图片资源是构建 UI 的基本技能之一,分为以下几类资源使用方式:
-
Flutter 中的图片来源类型
图片来源 示例 使用方式 本地 assets 项目中的 assets/images/
Image.asset(...)
网络图片 网络链接 Image.network(...)
内存 / 字节流 Uint8List 数据 Image.memory(...)
文件系统图片 本地文件路径 Image.file(...)
-
使用本地图片(
assets
)-
步骤一:创建
assets
目录在项目根目录下创建文件夹:
/assets/images/
放入图片,例如:
assets/images/logo.png
-
步骤二:配置
pubspec.yaml
打开
pubspec.yaml
,添加以下内容并取消注释缩进对齐:flutter:uses-material-design: trueassets:- assets/images/logo.png# 或包含整个文件夹:# - assets/images/
注意:
-
缩进要使用空格(不能用 Tab)
-
图片路径对大小写敏感
-
-
步骤三:使用
Image.asset
显示图片Image.asset('assets/images/logo.png',width: 200,height: 100,fit: BoxFit.cover, // 控制缩放裁剪方式 )
-
-
使用网络图片(
Image.network
)Image.network('https://flutter.dev/images/flutter-logo-sharing.png',width: 200,height: 100,fit: BoxFit.contain,loadingBuilder: (context, child, progress) {if (progress == null) return child;return CircularProgressIndicator();},errorBuilder: (context, error, stackTrace) {return Icon(Icons.error);}, )
建议总是配
loadingBuilder
和errorBuilder
处理网络情况。 -
图片控件常用属性
属性名 类型 说明 width
double
图片宽度 height
double
图片高度 fit
BoxFit
图片缩放裁剪方式,如 contain
、cover
color
Color
给图片加上颜色遮罩(配合 colorBlendMode
)repeat
ImageRepeat
图片重复方式(如 repeat-x) alignment
Alignment
图片对齐方式 -
图片裁剪、圆形、边框示例
-
圆形头像
ClipOval(child: Image.asset('assets/images/avatar.jpg',width: 100,height: 100,fit: BoxFit.cover,), )
-
圆角图片
ClipRRect(borderRadius: BorderRadius.circular(12),child: Image.asset('assets/images/banner.jpg'), )
-
-
示例
class ImageExample extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("图片示例")),body: Column(children: [Text("本地图片:"),Image.asset('assets/images/ic_launcher.png', width: 100),SizedBox(height: 20),Text("网络图片:"),Image.network("https://www.163987.com/d/file/p/2023/05-12/01f170d69eace10455c7116e98290099.png",width: 100)],));} }
-
总结
目标 方法 加载项目中的图片 Image.asset('路径')
加载网络图片 Image.network('url')
加载本地文件图片 Image.file(File('路径'))
加载内存字节图片 Image.memory(Uint8List)
-
-
字体和图标配置
-
使用字体
-
步骤一:添加字体文件
在项目中创建字体目录:
assets/fonts/
放入字体文件,例如:
assets/fonts/Pacifico-Regular.ttf
-
步骤二:配置
pubspec.yaml
在
flutter:
区块下添加字体配置(注意缩进!):flutter:uses-material-design: truefonts:- family: Pacificofonts:- asset: assets/fonts/Pacifico-Regular.ttf
-
步骤三:使用字体
Text('Hello 字体',style: TextStyle(fontFamily: 'Pacifico',fontSize: 32,), )
-
-
使用内置图标(Material Icons)
Flutter 默认包含 Material Icons 图标库,只要:
flutter:uses-material-design: true
即可使用:
Icon(Icons.favorite, color: Colors.red)
-
-
pubspec.yaml 中资源声明
Flutter 中的
assets
是项目中包含的静态资源,例如:-
图片(PNG、JPG、SVG)
-
音频(MP3、WAV)
-
字体文件(TTF)
-
JSON / 文本 / 配置文件等
这些资源 必须在
pubspec.yaml
中显式声明 才能在应用中使用。-
声明单个文件
flutter:assets:- assets/images/logo.png
-
声明整个文件夹
flutter:assets:- assets/images/- assets/audio/
-
注意事项
项 说明 缩进 必须是 2 个空格,不能用 Tab! 区分大小写 logo.PNG
≠logo.png
文件路径 必须真实存在,拼写要对 不支持通配 不能写成 assets/images/*.png
,只能手动列出或列目录修改后需 每次更改 assets
配置都应运行flutter pub get
或重启 IDE 使其生效
-