学习 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
-
设置环境变量
-
在系统环境变量中新建变量
tex变量名:PUB_HOSTED_URL 变量值:https://pub.flutter-io.cntex变量名:FLUTTER_STORAGE_BASE_URL 变量值:https://storage.flutter-io.cn -
在系统变量 PATH 中添加 Flutter bin目录
texD:\flutter_windows_3.24.1-stable\flutter\bin -
Android Studio 下载 SDK 工具和 Android SDK Comman-line Tools 并下载 Flutter 和 Dart 插件
-
执行命令
texflutter 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 结果
powershell[√] 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 apps X 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 仅依赖构造时传入的数据。
dartclass HelloText extends StatelessWidget { final String name; const HelloText({super.key, required this.name}); @override Widget build(BuildContext context) { return Text('Hello, $name'); } } -
-
StatefulWidget(有状态组件)
StatefulWidget是 可变的 ,拥有自己的状态对象State,当状态改变时会触发 UI 重新构建 (setState())。适用场景:
-
UI 需要根据用户交互或数据更新而改变
-
比如按钮点击计数、输入框内容、动画等。
dartclass CounterWidget extends StatefulWidget { const CounterWidget({super.key}); @override State<CounterWidget> createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { int _count = 0; void _increment() { setState(() { _count++; }); } @override 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,它们像"树枝"一样组成整个页面的布局和逻辑
mathematicaMaterialApp └── 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内容为dartimport 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp(); @override Widget build(BuildContext context) { return const MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { const HelloWorldPage(); @override Widget build(BuildContext context) { return const Scaffold( body: Center( child: Text( 'Hello World', style: TextStyle(fontSize: 24), ), ), ); } }
5. Flutter 组件详解
5.1 基础组件
-
Text(文本显示)
用于在界面中显示一段文本
dartText('Hello Flutter')常用属性:
属性名 类型 说明 styleTextStyle设置字体大小、颜色、粗细、行高等 textAlignTextAlign文本对齐方式(如 center、left)maxLinesint显示的最大行数 overflowTextOverflow文本超出时的处理(如 ellipsis)示例
dartText( '欢迎学习 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()加载内存中的图片 示例
dartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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 风格的图标
基本用法
dartIcon(Icons.home)常用属性
属性名 说明 Icons.xxx图标名,Flutter 内置许多图标 size图标大小 color图标颜色 示例
dartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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 组合体。常用属性
属性 类型 说明 childWidget 子组件 width/heightdouble 设置容器的宽度和高度 marginEdgeInsets外边距 paddingEdgeInsets内边距(对子组件生效) colorColor 背景颜色(不能与 decoration.color同时使用)alignmentAlignment控制子组件在容器内的位置 decorationBoxDecoration背景装饰(如圆角、边框、背景图等) transformMatrix4容器的几何变换(如旋转、缩放、平移) 示例
-
设置宽高 + 背景色 + 子组件居中
dartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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)), ); } } -
设置内边距和外边距
dartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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('带边距的文本'), ); } }
-
-
使用装饰
decorationdartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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('装饰效果')), ); } } -
添加变换(旋转)
dartimport 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { MyApp(); @override Widget build(BuildContext context) { return MaterialApp( home: HelloWorldPage(), ); } } class HelloWorldPage extends StatelessWidget { HelloWorldPage(); @override 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) 的布局组件。它的作用是:在子组件的外部(但在边框内部)增加空白区域。
语法结构
dartPadding( padding: EdgeInsets.all(8.0), // 设置内边距 child: Text('Hello Padding'), )示例
-
四边统一内边距
dartPadding( padding: EdgeInsets.all(16), child: Text('我有 16 的内边距'), ) -
水平、垂直内边距不同
dartPadding( padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12), child: Text('左右 24,上下 12'), ) -
仅指定某个方向
dartPadding( padding: EdgeInsets.only(top: 20, left: 10), child: Text('仅上边距 20,左边距 10'), )Padding与Container的区别特性 PaddingContainer设置内边距 专门用于设置内边距 (但只是组合属性的一部分) 设置颜色、大小 不支持 可以设置宽高、颜色、装饰等 推荐场景 专注间距控制 通用容器,做样式和布局控制更全面 -
Align(对齐)
Align是 Flutter 中用于 对子组件进行位置控制 的组件。它会在自身范围内,将child放置到指定的位置(例如居中、左上、右下等)基本语法
dartAlign( 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)表示正中间。"
示例
-
文字显示在右下角
dartAlign( alignment: Alignment.bottomRight, child: Text('右下角文字'), ) -
放一张图片到左上角
dartAlign( alignment: Alignment.topLeft, child: Image.asset('assets/images/avatar.png', width: 60), ) -
附加属性
widthFactor和heightFactor这些属性可以影响 Align 本身的大小
-
widthFactor:子组件宽度 × 倍数,作为 Align 的宽度; -
heightFactor:子组件高度 × 倍数,作为 Align 的高度;
dartAlign( alignment: Alignment.center, widthFactor: 2, heightFactor: 2, child: Text('我是 2 倍大'), ) -
-
和其他对齐组件的区别
组件 功能描述 Align精确控制子组件在父组件中的位置 Center相当于 Align(alignment: Alignment.center)Padding设置内边距,但不能控制子组件的具体位置 Positioned用于 Stack中,绝对定位
- "
-
Center(居中)
Center是一个非常简单的布局组件,它的作用是:将子组件放在父容器的中心位置基本语法
dartCenter( child: Text('居中显示'), )它会自动让
Text或其他子组件在父容器中 水平居中 + 垂直居中示例
-
居中显示文本
dartCenter( child: Text( 'Hello Center', style: TextStyle(fontSize: 24), ), ) -
居中显示图片
dartCenter( child: Image.asset('assets/images/logo.png', width: 100), ) -
结合
Container使用dartContainer( width: 300, height: 300, color: Colors.blue.shade100, child: Center( child: Text('我是居中的文字'), ), ) -
Center和其他布局组件的区别组件 用途 特点 Center子组件居中 最简单,等价于 Align.centerAlign子组件任意对齐 更灵活,需要手动指定 alignmentPadding增加空白区域,但不控制对齐方式 PositionedStack中做绝对定位需要配合 Stack使用
-
-
Row(水平排列)
Row是一个横向布局组件,用于 将多个组件水平排列在一行内基本语法
dartRow( children: [ Text('A'), Text('B'), Text('C'), ], )这段代码会将
A B C横向排在一行里。-
常用属性详情
属性名 类型 说明 childrenList<Widget>子组件列表 mainAxisAlignmentMainAxisAlignment主轴(水平方向)对齐方式 crossAxisAlignmentCrossAxisAlignment交叉轴(垂直方向)对齐方式 mainAxisSizeMainAxisSize主轴尺寸:最大/最小(是否占满可用空间) textDirectionTextDirection布局方向:从左到右(默认)还是从右到左 -
mainAxisAlignment对齐选项(水平)属性 效果 MainAxisAlignment.start左对齐(默认) MainAxisAlignment.center水平居中 MainAxisAlignment.end右对齐 MainAxisAlignment.spaceBetween两端对齐,子项平均分布 MainAxisAlignment.spaceAround子项周围空白相等 MainAxisAlignment.spaceEvenly子项之间空白完全相等 示例
dartRow( 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是一个 竖直方向布局组件 ,可以让多个子组件 从上到下一次排列基本语法
dartColumn( children: [ Text('第一行'), Text('第二行'), Text('第三行'), ], )-
常用属性解释
属性名 类型 说明 childrenList<Widget>子组件列表 mainAxisAlignmentMainAxisAlignment主轴(竖直方向)对齐方式 crossAxisAlignmentCrossAxisAlignment交叉轴(水平方向)对齐方式 mainAxisSizeMainAxisSize主轴大小控制(是否占满可用垂直空间) -
主轴对齐(mainAxisAlignment)
控制子组件在竖直方向上的排列方式:
属性值 效果 MainAxisAlignment.start从顶部开始(默认) MainAxisAlignment.center垂直居中 MainAxisAlignment.end底部对齐 MainAxisAlignment.spaceBetween上下贴边,中间平均分布 MainAxisAlignment.spaceAround每个子组件周围间距相等 MainAxisAlignment.spaceEvenly所有子组件间距完全相等 -
交叉轴对齐(crossAxisAlignment)
控制子组件在水平方向上的对齐方式
属性值 效果 CrossAxisAlignment.start左对齐(默认) CrossAxisAlignment.center水平居中 CrossAxisAlignment.end右对齐 CrossAxisAlignment.stretch拉伸子组件到最大宽度
示例
-
简单垂直排布
dartColumn( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: const [ Text('标题'), SizedBox(height: 10), Text('副标题'), SizedBox(height: 10), Icon(Icons.star, size: 32), ], ) -
加背景 + 居中演示(配合 Container)
dartContainer( 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 轴 (前后)方向叠加在一起基本语法
dartStack( children: [ Container(width: 200, height: 200, color: Colors.blue), Positioned( top: 20, left: 20, child: Icon(Icons.star, size: 50, color: Colors.white), ), ], )-
常用属性解释
属性名 类型 说明 childrenList<Widget>所有子组件,越靠后越在上层 alignmentAlignment控制非 Positioned 子组件的位置 fitStackFit控制子组件尺寸如何适应 Stack clipBehaviorClip是否裁剪超出部分(默认 Clip.hardEdge) -
StackvsPositioned-
Stack用来定义多个叠加的层 -
Positioned用来对某个子组件进行绝定位
和基本语法示例对比
dartStack( children: [ Container(color: Colors.yellow, width: 200, height: 200), Positioned( bottom: 10, right: 10, child: Text('右下角'), ), ], ) -
-
alignment:对非 Positioned 的子组件对齐
dartStack( 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立体按钮dartContainer( child: Column( children: [ ElevatedButton( onPressed: () { print('点击了 ElevatedButton'); }, child: Text('确定'), ) ], ), color: Colors.white, )常用于强调主要操作,例如 "登录"、"提交"。
-
TextButton(纯文本按钮)dartTextButton( onPressed: () { print('点击了 TextButton'); }, child: Text('取消'), )用于不那么显眼的按钮,比如"忘记密码"、"查看更多"。
-
OutlinedButton(带边框按钮)dartOutlinedButton( onPressed: () { print('点击了 OutlinedButton'); }, child: Text('边框按钮'), )用于中性操作,比如"跳过"、"稍后再说"。
-
自定义按钮样式
三种按钮都支持使用
style参数来自定义外观,使用ButtonStyle类dartElevatedButton( 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)
基本语法
dartGestureDetector( onTap: () { print('点击了组件'); }, child: Container( color: Colors.blue, padding: EdgeInsets.all(20), child: Text('点我'), ), )-
常用事件一览
属性名 类型 说明 onTapvoid Function()单击 onDoubleTapvoid Function()双击 onLongPressvoid Function()长按 onPanUpdateFunction(DragUpdateDetails)拖动时触发(全向) onPanStart/onPanEnd- 拖动开始 / 结束 onScaleUpdateFunction(ScaleUpdateDetails)双指缩放
示例
-
点击、长按、双击事件
dartGestureDetector( onTap: () => print('点击'), onDoubleTap: () => print('双击'), onLongPress: () => print('长按'), child: Container( padding: EdgeInsets.all(20), color: Colors.lightGreen, child: Text('点我试试'), ), ) -
拖动(onPanUpdate)
dartGestureDetector( 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)
dartGestureDetector( onScaleUpdate: (details) { print('缩放比例:${details.scale}'); }, child: Image.asset('assets/images/logo.png'), )
总结
-
| 功能 | 是否支持 | 示例属性 |
|---|---|---|
| 点击 | 支持 | onTap |
| 双击 | 支持 | onDoubleTap |
| 长按 | 支持 | onLongPress |
| 拖动 | 支持 | onPanUpdate |
| 缩放 | 支持 | onScaleUpdate |
| 支持嵌套其他组件 | 支持 | child |
| 无视觉效果(非按钮) | 支持 | 需要自定义样式 |
-
InkWell(水波纹效果点击)
InkWell是一个 带水波纹(涟漪)点击效果的手势识别组件。 相比GestureDetector它有更好的 Material 设计风格的视觉效果它属于 Material 组件体系的一部分,使用时需要有
Material组件作为"水波纹的绘制容器"基本用法
dartInkWell( onTap: () { print('点击了 InkWell'); }, child: Padding( padding: EdgeInsets.all(16), child: Text('点我'), ), )点击时会看到水波纹从点击点扩散开来
-
常用属性
属性名 类型 说明 onTapvoid Function()?点击事件 onDoubleTapvoid Function()?双击事件 onLongPressvoid Function()?长按事件 borderRadiusBorderRadius设置水波纹圆角 splashColorColor设置水波纹颜色 highlightColorColor按下时的背景色 childWidget显示内容 -
配合
Material使用 (必须)dartMaterial( 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区别对比对比点 GestureDetectorInkWell是否有视觉反馈 无水波纹 有水波纹 是否依赖 Material不依赖 必须依赖 Material 父组件 支持的手势种类 拖动、缩放、滑动等更丰富 主要用于点击相关 使用场景 自定义复杂交互 通常用于按钮、卡片、列表点击反馈等
-
5.4 输入框和表单
-
TextField(文本输入)
TextField是最常用的文本输入组件,用于实现表单的输入、搜索框、聊天框等各种输入功能基本用法
dartTextField( decoration: InputDecoration( labelText: '用户名', hintText: '请输入用户名', border: OutlineInputBorder(), ), )效果:一个带标签、提示文字、边框的输入框
-
常用属性详情
属性名 类型 说明 controllerTextEditingController控制和监听输入框内容 decorationInputDecoration装饰输入框(如提示、图标、边框等) obscureTextbool是否隐藏输入内容(用于密码) keyboardTypeTextInputType输入类型(文本、数字、邮箱等) maxLinesint输入框最大行数 onChangedFunction(String)文本改变时回调 onSubmittedFunction(String)用户按下"完成/提交"时的回调 enabledbool是否可编辑 readOnlybool是否只读
示例
-
带控制器示例(获取输入内容)
dartclass TextFieldExample extends StatelessWidget { final TextEditingController _controller = TextEditingController(); @override 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('提交')) ], ), ), ); } } -
密码框(隐藏输入)
dartTextField( obscureText: true, decoration: InputDecoration( labelText: '密码', border: OutlineInputBorder(), ), )不同输入类型
输入类型 示例设置 文本(默认) keyboardType: TextInputType.text数字 keyboardType: TextInputType.number电话 keyboardType: TextInputType.phone邮箱 keyboardType: TextInputType.emailAddress -
多行输入
dartTextField( maxLines: 5, decoration: InputDecoration(labelText: '多行备注'), ) -
自定义装饰 InputDecoration 示例
dartTextField( decoration: InputDecoration( prefixIcon: Icon(Icons.person), suffixIcon: Icon(Icons.clear), labelText: '用户名', hintText: '请输入用户名', border: OutlineInputBorder(), ), )
-
-
Checkbox(多选框)
Checkbox是一个可以勾选/取消的组件,只有两个状态(true/false) 可以搭配文字或图标一起使用。基本用法
dartbool _isChecked = false; Checkbox( value: _isChecked, onChanged: (bool? value) { setState(() { _isChecked = value!; }); }, )必须在
StatefulWidget中使用,因为复选框的值需要动态更新。示例
dartclass CheckBoxDemo extends StatefulWidget { @override _CheckBoxDemoState createState() => _CheckBoxDemoState(); } class _CheckBoxDemoState extends State<CheckBoxDemo> { bool _isSelected = false; @override 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 ? "已选中" : "未选中"), ], ), ), ); } }常用属性
属性名 类型 说明 valuebool当前是否勾选 onChanged(bool?) → void勾选状态变化时的回调函数 activeColorColor选中时的颜色 checkColorColor号颜色 tristatebool是否支持三种状态(true/false/null) 搭配
CheckboxListTitle(复选框 + 标题 + 子标题)dartCheckboxListTile( 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一起使用。最基本的用法示例
dartRadio<int>( value: 1, groupValue: _selectedValue, onChanged: (int? value) { setState(() { _selectedValue = value!; }); }, )-
value:表示当前这个单选按钮的值 -
groupValue:表示当前"选中的值" -
onChanged:当点击时调用,传入的就是value
选择性别示例:
dartclass RadioDemo extends StatefulWidget { @override _RadioDemoState createState() => _RadioDemoState(); } class _RadioDemoState extends State<RadioDemo> { String _gender = "男"; @override 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"), ], ), ); } }常用属性一览
属性名 类型 说明 valueT当前这个选项的值 groupValueT当前组中被选中的值 onChangedFunction(T?)点击时回调 activeColorColor选中状态颜色 toggleablebool是否支持再次点击取消(Flutter 3.7+) -
-
Switch(开关)
Switch是 Flutter 提供的滑动切换组件 ,只有两个状态:true(开启)和false(关闭)最基本的用法
dartbool _isOn = false; Switch( value: _isOn, onChanged: (bool value) { setState(() { _isOn = value; }); }, )必须在
StatefulWidget中使用,因为开关状态需要实时更新。示例:
-
控制某功能开关
dartclass SwitchDemo extends StatefulWidget { @override _SwitchDemoState createState() => _SwitchDemoState(); } class _SwitchDemoState extends State<SwitchDemo> { bool _isDarkMode = false; @override 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 ? '暗黑模式已开启' : '暗黑模式已关闭'), ], ), ); } }
常用属性
属性名 类型 说明 valuebool当前开关状态 onChanged(bool) → void状态变化回调函数 activeColorColor开启时的主色(圆点颜色) activeTrackColorColor开启时轨道颜色 inactiveThumbColorColor关闭时圆点颜色 inactiveTrackColorColor关闭时轨道颜色 materialTapTargetSizeMaterialTapTargetSize调整点击区域大小 -
-
Form 与 FormField(表单管理)
在 Flutter 中,
Form和FormField是用于统一管理多个输入组件的表单系统,可以方便地进行表单验证、提交等操作,常用于登录、注册、反馈等界面。-
什么是
Form和FormField组件 作用说明 Form表单容器,用于管理一组输入项(字段) FormField表单字段的基类(如 TextFormField) TextFormField是最常用的FormField实现,是带表单验证功能的输入框 -
Form的基本结构dartfinal _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()重置所有字段内容和状态 -
完整示例
dartclass FormExample extends StatefulWidget { @override _FormExampleState createState() => _FormExampleState(); } class _FormExampleState extends State<FormExample> { final _formKey = GlobalKey<FormState>(); String _username = ''; String _password = ''; @override 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('提交'), ), ], ), ), ), ); } } -
TextFieldVSTextFormField区别项 TextFieldTextFormField表单验证支持 无验证方法 支持 validator/onSaved 等 与 Form 配合使用 需要单独管理状态 可统一使用 Form 管理 推荐使用场景 简单输入框 表单场景(如登录、注册等) -
一些常用方法(FormState)
方法名 说明 validate()所有字段验证,返回布尔值 save()调用每个字段的 onSaved()reset()重置整个表单
-
5.5 滚动视图
-
ListView(列表)
ListView是一个 可滚动的线性列表视图组件 可以直接或水平显示一系列子组件-
最基本的用法
dartListView( children: [ ListTile(title: Text('第1项')), ListTile(title: Text('第2项')), ListTile(title: Text('第3项')), ], )默认是垂直方向的,超出屏幕会自动滚动。
-
常见构造方式
-
ListView+children: 静态少量内容 -
ListView.builder: 动态列表(推荐) -
ListView.separated: 带分隔线 -
ListView.custom: 高级自定义构造(极少用)
-
-
常用属性
属性名 类型 说明 itemCountint列表项数量(用于 builder) itemBuilderIndexedWidgetBuilder构建每项内容的方法 scrollDirectionAxis滚动方向( Axis.vertical/horizontal)reversebool是否反转列表显示顺序 shrinkWrapbool是否根据内容自动收缩高度 physicsScrollPhysics滚动行为(如禁止、弹性等) paddingEdgeInsets设置内边距 -
示例
dartclass ListViewDemo extends StatelessWidget { final List<String> items = List.generate(20, (index) => '项目 $index'); @override 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(常规固定列数网格)dartGridView.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(推荐用于大数据列表)dartGridView.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(指定最大宽度自动适配列数)dartGridView.extent( maxCrossAxisExtent: 100, // 每个项最大宽度,系统自动决定多少列 children: List.generate(20, (index) { return Container( alignment: Alignment.center, color: Colors.orange[100 * ((index % 8) + 1)], child: Text('Item $index'), ); }), )
-
-
常用属性说明
属性名 类型 说明 crossAxisCountint每行显示的列数 mainAxisSpacingdouble每行之间的间距(垂直方向) crossAxisSpacingdouble每列之间的间距(水平方向) childAspectRatiodouble宽高比(宽/高) shrinkWrapbool是否根据内容高度自适应(适用于嵌套) physicsScrollPhysics滚动行为(常用于嵌套时禁用滚动) -
示例
dartimport 'package:flutter/material.dart'; class GridViewExample extends StatelessWidget { @override 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)错误。-
基本用法
dartSingleChildScrollView( child: Column( children: [ Text('A'), Text('B'), Text('C'), // 很多内容... ], ), )SingleChildScrollView的child只能是 一个 Widget,通常搭配Column使用。 -
典型使用场景
-
登录页 / 注册页(键盘弹出时防止布局溢出)
-
表单页面(需要整体滚动)
-
多控件组合的页面(不是列表)
-
-
重要属性说明
属性名 类型 说明 scrollDirectionAxis滚动方向,默认是 Axis.verticalpaddingEdgeInsets内边距 reversebool是否反向滚动 physicsScrollPhysics滚动行为(如弹性、不可滚动) controllerScrollController控制滚动、监听滚动位置等 -
示例
dartimport 'package:flutter/material.dart'; class ScrollDemo extends StatelessWidget { @override 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区别对比对比项 SingleChildScrollViewListView用法场景 多个固定控件、表单页面 长列表、动态项 性能优化 没有懒加载,所有内容一次性渲染 支持懒加载 子组件结构 一个 Widget(如 Column)包多个控件多个 Widget 构建 嵌套使用 更适合嵌套在页面中或布局中 嵌套需注意高度限制和滚动冲突
-
5.6 导航和路由
-
Navigator 介绍
Navigator是用于管理页面(Route)跳转和堆栈操作的组件,类似网页的前进、后退、跳转操作。-
什么是
Navigator?Navigator是一个页面堆栈管理器,你可以:-
push:打开新页面(入栈)
-
pop:返回上一个页面(出栈)
-
replace:替换当前页面
-
清空所有页面再跳转:跳转并清空历史
Navigator 通常配合
MaterialPageRoute或named route使用。 -
-
最基础的页面跳转方式
-
跳转到新页面(push)
dartNavigator.push( context, MaterialPageRoute(builder: (context) => SecondPage()), ); -
返回上一级页面(pop)
dartNavigator.pop(context);
-
-
带返回值的页面跳转
A → B,B返回数据给A:
在 A 页面:
dartvoid _goToSecondPage() async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => SecondPage()), ); print("从第二页返回的数据: $result"); }在 B 页面:
dartElevatedButton( onPressed: () { Navigator.pop(context, "这是返回值"); }, child: Text("返回并携带数据"), ) -
使用命名路由(推荐方式)
-
定义路由表
dartMaterialApp( initialRoute: '/', routes: { '/': (context) => HomePage(), '/second': (context) => SecondPage(), }, ) -
跳转方式
dartNavigator.pushNamed(context, '/second'); -
返回方式
dartNavigator.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()
作用:** 打开(压栈)一个新页面**
dartNavigator.push( context, MaterialPageRoute(builder: (context) => SecondPage()), );-
context:当前页面的上下文 -
MaterialPageRoute:常用的页面过渡动画(安卓风格) -
SecondPage():你要跳转的新页面 Widget
示例
dartElevatedButton( onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => SecondPage()), ); }, child: Text("去第二页"), ) -
-
Navigator.pop()
作用:返回(出栈)上一个页面
dartNavigator.pop(context);可选地返回一个值:
dartNavigator.pop(context, "返回的数据"); -
push+pop结合使用(带返回值)-
第一个页面
dartvoid _goToSecondPage() async { final result = await Navigator.push( context, MaterialPageRoute(builder: (context) => SecondPage()), ); print("从第二页返回的数据是:$result"); } -
第二个页面
dartElevatedButton( onPressed: () { Navigator.pop(context, "你好,这是返回值"); }, child: Text("返回并传数据"), )
-
-
Navigator 的"堆栈"原理图示
scss初始: [ 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 应用中几乎每个页面都会使用的标准导航栏。
-
基本语法
dartScaffold( appBar: AppBar( title: Text('我是标题'), ), body: Center(child: Text('内容')), ) -
常用属性说明
属性名 类型 作用说明 titleWidget应用栏的标题,通常是 TextleadingWidget左侧图标(默认是返回箭头) actionsList<Widget>右侧图标按钮列表 backgroundColorColor背景颜色 centerTitlebool是否居中标题(iOS 默认为 true) elevationdouble阴影高度(默认 4) bottomPreferredSizeWidget下方扩展区域,如 TabBar -
示例
dartimport 'package:flutter/material.dart'; class AppBarExample extends StatelessWidget { @override 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 部件放进去就可以构成完整的页面。
-
基本使用方式
dartScaffold( appBar: AppBar(title: Text("首页")), body: Center(child: Text("Hello World")), ) -
Scaffold 的常用属性详解
属性名 类型 作用说明 appBarAppBar页面顶部导航栏 bodyWidget页面主要内容区域 floatingActionButtonFloatingActionButton页面悬浮按钮 drawerDrawer左侧滑出菜单 bottomNavigationBarBottomNavigationBar页面底部导航栏 backgroundColorColor页面背景色 persistentFooterButtonsList<Widget>固定在底部的按钮组 bottomSheetWidget页面底部悬浮层 -
示例
dartimport 'package:flutter/material.dart'; class ScaffoldExample extends StatelessWidget { @override 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底部固定菜单栏 bottomNavigationBarorBottomAppBar显示提示 ScaffoldMessenger.of(context).showSnackBar(...)
-
-
Drawer(抽屉导航)
Drawer是 Scaffold 提供的一个侧边导航菜单,通常从左边滑出,用于展示导航选项、用户信息等。-
基本结构
dartDrawer( 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)
-
手动打开
dartScaffold.of(context).openDrawer(); // 仅限于在子 Widget 中使用 Builder 包裹 -
手动关闭
dartNavigator.pop(context)
-
-
示例
dartclass DrawerExample extends StatelessWidget { @override 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)-
基本用法
dartScaffold( bottomNavigationBar: BottomNavigationBar( currentIndex: 0, // 当前选中索引 onTap: (index) { // 切换页面逻辑 }, items: [ BottomNavigationBarItem( icon: Icon(Icons.home), label: '首页', ), BottomNavigationBarItem( icon: Icon(Icons.person), label: '我的', ), ], ), ) -
示例
dartimport 'package:flutter/material.dart'; class BottomNavExample extends StatefulWidget { @override _BottomNavExampleState createState() => _BottomNavExampleState(); } class _BottomNavExampleState extends State<BottomNavExample> { int _currentIndex = 0; final List<Widget> _pages = [ Center(child: Text('首页内容')), Center(child: Text('分类内容')), Center(child: Text('我的内容')) ]; @override 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: "我的"), ], ), ); } } -
属性说明
属性名 类型 说明 itemsList 菜单项(最少2项) currentIndexint 当前选中项的索引 onTapFunction(int) 点击导航项回调 typeBottomNavigationBarType 显示样式: fixed(默认)或shifting(动效)selectedItemColorColor 选中项颜色 unselectedItemColorColor 未选中项颜色 backgroundColorColor 背景色
-
6. 状态管理基础
6.1 什么是状态?
简单来说,状态就是某个变量的值 当这个值发生变化时,对应的 UI会自动刷新 展示新的内容,
比如:
-
一个计数器的数字是状态 (
count = 3) -
一个按钮是否选中是状态(
isSelected = true) -
一个页面当前是"加载中"还是"已完成"是状态(
loading = true / false)
示例
dart
int count = 0; // 这就是一个状态
ElevatedButton(
onPressed: () {
setState(() {
count++;
});
},
child: Text('点击了 $count 次'),
)
-
Flutter 中状态是怎么驱动 UI 的?
Flutter 的 Widget 是声明时UI,它不是手动改动控件,而是重新构建:
dart// 当状态改变时 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目录在项目根目录下创建文件夹:
bash/assets/images/放入图片,例如:
bashassets/images/logo.png -
步骤二:配置
pubspec.yaml打开
pubspec.yaml,添加以下内容并取消注释缩进对齐:yamlflutter: uses-material-design: true assets: - assets/images/logo.png # 或包含整个文件夹: # - assets/images/注意:
-
缩进要使用空格(不能用 Tab)
-
图片路径对大小写敏感
-
-
步骤三:使用
Image.asset显示图片dartImage.asset( 'assets/images/logo.png', width: 200, height: 100, fit: BoxFit.cover, // 控制缩放裁剪方式 )
-
-
使用网络图片(
Image.network)dartImage.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处理网络情况。 -
图片控件常用属性
属性名 类型 说明 widthdouble图片宽度 heightdouble图片高度 fitBoxFit图片缩放裁剪方式,如 contain、covercolorColor给图片加上颜色遮罩(配合 colorBlendMode)repeatImageRepeat图片重复方式(如 repeat-x) alignmentAlignment图片对齐方式 -
图片裁剪、圆形、边框示例
-
圆形头像
dartClipOval( child: Image.asset( 'assets/images/avatar.jpg', width: 100, height: 100, fit: BoxFit.cover, ), ) -
圆角图片
dartClipRRect( borderRadius: BorderRadius.circular(12), child: Image.asset('assets/images/banner.jpg'), )
-
-
示例
dartclass ImageExample extends StatelessWidget { @override 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)
-
-
字体和图标配置
-
使用字体
-
步骤一:添加字体文件
在项目中创建字体目录:
bashassets/fonts/放入字体文件,例如:
bashassets/fonts/Pacifico-Regular.ttf -
步骤二:配置
pubspec.yaml在
flutter:区块下添加字体配置(注意缩进!):yamlflutter: uses-material-design: true fonts: - family: Pacifico fonts: - asset: assets/fonts/Pacifico-Regular.ttf -
步骤三:使用字体
dartText( 'Hello 字体', style: TextStyle( fontFamily: 'Pacifico', fontSize: 32, ), )
-
-
使用内置图标(Material Icons)
Flutter 默认包含 Material Icons 图标库,只要:
yamlflutter: uses-material-design: true即可使用:
dartIcon(Icons.favorite, color: Colors.red)
-
-
pubspec.yaml 中资源声明
Flutter 中的
assets是项目中包含的静态资源,例如:-
图片(PNG、JPG、SVG)
-
音频(MP3、WAV)
-
字体文件(TTF)
-
JSON / 文本 / 配置文件等
这些资源 必须在
pubspec.yaml中显式声明 才能在应用中使用。-
声明单个文件
yamlflutter: assets: - assets/images/logo.png -
声明整个文件夹
yamlflutter: assets: - assets/images/ - assets/audio/ -
注意事项
项 说明 缩进 必须是 2 个空格,不能用 Tab! 区分大小写 logo.PNG≠logo.png文件路径 必须真实存在,拼写要对 不支持通配 不能写成 assets/images/*.png,只能手动列出或列目录修改后需 每次更改 assets配置都应运行flutter pub get或重启 IDE 使其生效
-