找一个网站做优化分析app界面设计属于什么设计
学习 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')常用属性:
属性名 类型 说明 styleTextStyle设置字体大小、颜色、粗细、行高等 textAlignTextAlign文本对齐方式(如 center、left)maxLinesint显示的最大行数 overflowTextOverflow文本超出时的处理(如 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 组合体。常用属性
属性 类型 说明 childWidget 子组件 width/heightdouble 设置容器的宽度和高度 marginEdgeInsets外边距 paddingEdgeInsets内边距(对子组件生效) colorColor 背景颜色(不能与 decoration.color同时使用)alignmentAlignment控制子组件在容器内的位置 decorationBoxDecoration背景装饰(如圆角、边框、背景图等) transformMatrix4容器的几何变换(如旋转、缩放、平移) 示例
-
设置宽高 + 背景色 + 子组件居中
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('带边距的文本'),);} }
-
-
使用装饰
decorationimport '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的区别特性 PaddingContainer设置内边距 专门用于设置内边距 (但只是组合属性的一部分) 设置颜色、大小 不支持 可以设置宽高、颜色、装饰等 推荐场景 专注间距控制 通用容器,做样式和布局控制更全面 -
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.centerAlign子组件任意对齐 更灵活,需要手动指定 alignmentPadding增加空白区域,但不控制对齐方式 PositionedStack中做绝对定位需要配合 Stack使用
-
-
Row(水平排列)
Row是一个横向布局组件,用于 将多个组件水平排列在一行内基本语法
Row(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子项之间空白完全相等 示例
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('第三行'),], )-
常用属性解释
属性名 类型 说明 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拉伸子组件到最大宽度
示例
-
简单垂直排布
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),),], )-
常用属性解释
属性名 类型 说明 childrenList<Widget>所有子组件,越靠后越在上层 alignmentAlignment控制非 Positioned 子组件的位置 fitStackFit控制子组件尺寸如何适应 Stack clipBehaviorClip是否裁剪超出部分(默认 Clip.hardEdge) -
StackvsPositioned-
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('点我'),), )-
常用事件一览
属性名 类型 说明 onTapvoid Function()单击 onDoubleTapvoid Function()双击 onLongPressvoid Function()长按 onPanUpdateFunction(DragUpdateDetails)拖动时触发(全向) onPanStart/onPanEnd- 拖动开始 / 结束 onScaleUpdateFunction(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('点我'),), )点击时会看到水波纹从点击点扩散开来
-
常用属性
属性名 类型 说明 onTapvoid Function()?点击事件 onDoubleTapvoid Function()?双击事件 onLongPressvoid Function()?长按事件 borderRadiusBorderRadius设置水波纹圆角 splashColorColor设置水波纹颜色 highlightColorColor按下时的背景色 childWidget显示内容 -
配合
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区别对比对比点 GestureDetectorInkWell是否有视觉反馈 无水波纹 有水波纹 是否依赖 Material不依赖 必须依赖 Material 父组件 支持的手势种类 拖动、缩放、滑动等更丰富 主要用于点击相关 使用场景 自定义复杂交互 通常用于按钮、卡片、列表点击反馈等
-
5.4 输入框和表单
-
TextField(文本输入)
TextField是最常用的文本输入组件,用于实现表单的输入、搜索框、聊天框等各种输入功能基本用法
TextField(decoration: InputDecoration(labelText: '用户名',hintText: '请输入用户名',border: OutlineInputBorder(),), )效果:一个带标签、提示文字、边框的输入框
-
常用属性详情
属性名 类型 说明 controllerTextEditingController控制和监听输入框内容 decorationInputDecoration装饰输入框(如提示、图标、边框等) obscureTextbool是否隐藏输入内容(用于密码) keyboardTypeTextInputType输入类型(文本、数字、邮箱等) maxLinesint输入框最大行数 onChangedFunction(String)文本改变时回调 onSubmittedFunction(String)用户按下“完成/提交”时的回调 enabledbool是否可编辑 readOnlybool是否只读
示例
-
带控制器示例(获取输入内容)
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 ? "已选中" : "未选中"),],),),);} }常用属性
属性名 类型 说明 valuebool当前是否勾选 onChanged(bool?) → void勾选状态变化时的回调函数 activeColorColor选中时的颜色 checkColorColor号颜色 tristatebool是否支持三种状态(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"),],),);} }常用属性一览
属性名 类型 说明 valueT当前这个选项的值 groupValueT当前组中被选中的值 onChangedFunction(T?)点击时回调 activeColorColor选中状态颜色 toggleablebool是否支持再次点击取消(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 ? '暗黑模式已开启' : '暗黑模式已关闭'),],),);} }
常用属性
属性名 类型 说明 valuebool当前开关状态 onChanged(bool) → void状态变化回调函数 activeColorColor开启时的主色(圆点颜色) activeTrackColorColor开启时轨道颜色 inactiveThumbColorColor关闭时圆点颜色 inactiveTrackColorColor关闭时轨道颜色 materialTapTargetSizeMaterialTapTargetSize调整点击区域大小 -
-
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('提交'),),],),),),);} } -
TextFieldVSTextFormField区别项 TextFieldTextFormField表单验证支持 无验证方法 支持 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: 高级自定义构造(极少用)
-
-
常用属性
属性名 类型 说明 itemCountint列表项数量(用于 builder) itemBuilderIndexedWidgetBuilder构建每项内容的方法 scrollDirectionAxis滚动方向( Axis.vertical/horizontal)reversebool是否反转列表显示顺序 shrinkWrapbool是否根据内容自动收缩高度 physicsScrollPhysics滚动行为(如禁止、弹性等) paddingEdgeInsets设置内边距 -
示例
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'),);}), )
-
-
常用属性说明
属性名 类型 说明 crossAxisCountint每行显示的列数 mainAxisSpacingdouble每行之间的间距(垂直方向) crossAxisSpacingdouble每列之间的间距(水平方向) childAspectRatiodouble宽高比(宽/高) shrinkWrapbool是否根据内容高度自适应(适用于嵌套) physicsScrollPhysics滚动行为(常用于嵌套时禁用滚动) -
示例
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使用。 -
典型使用场景
-
登录页 / 注册页(键盘弹出时防止布局溢出)
-
表单页面(需要整体滚动)
-
多控件组合的页面(不是列表)
-
-
重要属性说明
属性名 类型 说明 scrollDirectionAxis滚动方向,默认是 Axis.verticalpaddingEdgeInsets内边距 reversebool是否反向滚动 physicsScrollPhysics滚动行为(如弹性、不可滚动) controllerScrollController控制滚动、监听滚动位置等 -
示例
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区别对比对比项 SingleChildScrollViewListView用法场景 多个固定控件、表单页面 长列表、动态项 性能优化 没有懒加载,所有内容一次性渲染 支持懒加载 子组件结构 一个 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('内容')), ) -
常用属性说明
属性名 类型 作用说明 titleWidget应用栏的标题,通常是 TextleadingWidget左侧图标(默认是返回箭头) actionsList<Widget>右侧图标按钮列表 backgroundColorColor背景颜色 centerTitlebool是否居中标题(iOS 默认为 true) elevationdouble阴影高度(默认 4) bottomPreferredSizeWidget下方扩展区域,如 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 的常用属性详解
属性名 类型 作用说明 appBarAppBar页面顶部导航栏 bodyWidget页面主要内容区域 floatingActionButtonFloatingActionButton页面悬浮按钮 drawerDrawer左侧滑出菜单 bottomNavigationBarBottomNavigationBar页面底部导航栏 backgroundColorColor页面背景色 persistentFooterButtonsList<Widget>固定在底部的按钮组 bottomSheetWidget页面底部悬浮层 -
示例
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底部固定菜单栏 bottomNavigationBarorBottomAppBar显示提示 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: "我的"),],),);} } -
属性说明
属性名 类型 说明 itemsList 菜单项(最少2项) currentIndexint 当前选中项的索引 onTapFunction(int) 点击导航项回调 typeBottomNavigationBarType 显示样式: fixed(默认)或shifting(动效)selectedItemColorColor 选中项颜色 unselectedItemColorColor 未选中项颜色 backgroundColorColor 背景色
-
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处理网络情况。 -
图片控件常用属性
属性名 类型 说明 widthdouble图片宽度 heightdouble图片高度 fitBoxFit图片缩放裁剪方式,如 contain、covercolorColor给图片加上颜色遮罩(配合 colorBlendMode)repeatImageRepeat图片重复方式(如 repeat-x) alignmentAlignment图片对齐方式 -
图片裁剪、圆形、边框示例
-
圆形头像
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 使其生效
-
