學習 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 使其生效
-