目錄
一、參考文檔
二、準備工作
下載Flutter SDK:
配置環境
解決環境報錯?zsh:command not found:flutter
執行【flutter doctor】測試效果
安裝Xcode IOS環境
需要安裝brew,通過brew安裝CocoaPods.
復制命令行,打開終端
分別執行下面命令
如圖所示
三、創建Flutter IOS項目
Mac 創建Flutter IOS項目
通過 sudo chmod -R 777 * 修改一下文件權限
Xcode 打開Flutter項目?
Android Studio創建Flutter項目
?Flutter目錄層級介紹
依賴庫/圖片的引用?
pub包管理系統:
?使用第三庫,在官網找到對應的庫
?復制地方庫的引用方式
四、Flutter簡單應用
1.主題設置
1.1 定義主題數據
1.2 狀態管理(以 Provider 為例)
1.3 在 MaterialApp 中應用主題
1.4 創建主題切換界面
2. 國際化
2.1 添加依賴
2.2 配置支持的語言
2.3 創建多語言資源文件
定義基礎接口
實現英語資源
實現中文資源
創建本地化代理
在 UI 中使用本地化字符串
3. 相機相冊調用
3.1 添加依賴
3.2 配置權限
iOS
Android
3.3 實現相機和相冊功能
3.4 高級功能
拍攝視頻
多選圖片
五、Flutter 調用原生代碼
基本原理
實現步驟
在 Flutter 端創建通道
在 Android 端實現(Kotlin)
在 iOS 端實現(Swift)
六、Flutter 打包工具
一、參考文檔
API文檔 | 鏈接 |
---|---|
Flutter地址 | https://docs.flutter.dev/ |
Homebrew地址 | https://brew.sh |
pub包管理系統 | The official repository for Dart and Flutter packages. |
Material Design官方Icons圖標 | https://fonts.google.com/icons |
二、準備工作
-
升級Macos系統為最新系統
-
安裝最新的Xcode
-
電腦上面需要安裝brew https://brew.sh/
-
安裝chrome瀏覽器(開發web用)
下載Flutter SDK:
FlutterSDK下載地址:?https://docs.flutter.dev/get-started/install
常用編譯軟件:
-
Visual Studio Code with the Flutter extension for VS Code.
-
Android Studio with the Flutter plugin for IntelliJ.
-
IntelliJ IDEA with both the Flutter plugin for IntelliJ and the Android plugin for IntelliJ.
下載zip并解壓到本地文件中
配置環境
-
打開命令行,執行【open ~/.bash_profile 】
-
把剛解壓好的FlutterSDK文件地址進行配置,把內容粘貼到.bash_profile文件
export PATH="$PATH:/home/yourusername/flutter/bin"
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
??????3.? 執行【source ~/.bash_profile 】,將.bash_profile文件生效
??????4. 執行【flutter doctor】測試效果。
注意哈:這樣配置,如果你只有(bash_profile,沒有zshrc文件)。
需要每次打開終端輸入一下 source ~/.bash_profile 命令,再使用flutter命令。不然會報錯。
zsh:command not found:flutter
像下面圖片效果:
解決環境報錯?zsh:command not found:flutter
1、執行:【open ~/.zshrc 】
2、如果 提示文件不存在,則執行:【vim ~/.zshrc 】新建一個新文件。
vim ~/.zshrc
再使用source命令重新加載一下:【source ~/.zshrc】,下次再編輯這個文件就可以直接執行:【open ~/.zshrc】
source ~/.zshrc
執行【flutter doctor】測試效果
這個時候試試關閉終端再輸入flutter doctor,此時Flutter SDK配置完成,按照下面提示進行安裝操作(下載Android SDK、Xcode、CocoaPods)。
安裝Xcode IOS環境
需要安裝brew,通過brew安裝CocoaPods.
Homebrew官網: https://brew.sh/
復制命令行,打開終端
分別執行下面命令
brew install cocoapods.pod setupsudo xcode-select --switch /Applications/xcode.app/contents/Developersudo xcodebuild -runFirstLaunch
如圖所示
brew doctor
三、創建Flutter IOS項目
Mac 創建Flutter IOS項目
sudo flutter create flutterdemo?sudo chmod -R 777 flutterdemo //修改一下文件權限 可讀。可寫
通過 sudo chmod -R 777 * 修改一下文件權限
Xcode 打開Flutter項目?
flutter run
flutter -d all
flutter -d chrome
Android Studio創建Flutter項目
?Flutter目錄層級介紹
依賴庫/圖片的引用?
pub包管理系統:
官網地址:https://pub.dev/
?使用第三庫,在官網找到對應的庫
?復制地方庫的引用方式
四、Flutter簡單應用
1.主題設置
在 Flutter 項目里,實現主題切換功能需要結合狀態管理和 Flutter 的主題系統。下面為你介紹實現主題切換的具體步驟:
1.1 定義主題數據
要先創建亮、暗兩種主題,并且設置好各自的顏色和樣式。
import 'package:flutter/material.dart';class AppThemes {static final lightTheme = ThemeData(brightness: Brightness.light,primaryColor: Colors.blue,scaffoldBackgroundColor: Colors.white,// 其他主題屬性...);static final darkTheme = ThemeData(brightness: Brightness.dark,primaryColor: Colors.blue,scaffoldBackgroundColor: Colors.black,// 其他主題屬性...);
}
1.2 狀態管理(以 Provider 為例)
接著創建一個主題狀態管理類,以此來保存和更新當前使用的主題。
import 'package:flutter/material.dart';class ThemeProvider with ChangeNotifier {ThemeMode _themeMode = ThemeMode.system;ThemeMode get themeMode => _themeMode;void toggleTheme(bool isDark) {_themeMode = isDark ? ThemeMode.dark : ThemeMode.light;notifyListeners();}void setSystemTheme() {_themeMode = ThemeMode.system;notifyListeners();}
}
1.3 在 MaterialApp 中應用主題
然后在應用的根 Widget 里配置主題,并監聽主題變化。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';void main() {runApp(ChangeNotifierProvider(create: (context) => ThemeProvider(),child: const MyApp(),),);
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Consumer<ThemeProvider>(builder: (context, themeProvider, child) {return MaterialApp(title: 'Flutter Theme Demo',theme: AppThemes.lightTheme,darkTheme: AppThemes.darkTheme,themeMode: themeProvider.themeMode,home: const HomePage(),);},);}
}
1.4 創建主題切換界面
最后添加一個用于切換主題的 UI 組件,像開關或按鈕。
class HomePage extends StatelessWidget {const HomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {final themeProvider = Provider.of<ThemeProvider>(context);final isDark = themeProvider.themeMode == ThemeMode.dark;return Scaffold(appBar: AppBar(title: const Text('主題切換示例'),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const Text('切換主題'),Switch(value: isDark,onChanged: (value) {themeProvider.toggleTheme(value);},),],),),);}
}
2. 國際化
在 Flutter 項目中設置國際化需要配置多語言資源并確保應用能根據系統語言自動切換。以下是實現步驟:
2.1 添加依賴
在pubspec.yaml
中添加flutter_localizations
和intl
插件:
dependencies:flutter:sdk: flutterflutter_localizations:sdk: flutterintl: ^0.18.1 # 最新版本
2.2 配置支持的語言
在MaterialApp
中指定支持的語言列表和本地化代理:
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter 國際化示例',// 支持的語言列表supportedLocales: [Locale('en', 'US'), // 英語Locale('zh', 'CN'), // 中文// 添加更多語言...],// 本地化代理localizationsDelegates: [AppLocalizations.delegate, // 自定義代理GlobalMaterialLocalizations.delegate, // Material組件本地化GlobalWidgetsLocalizations.delegate, // 小部件庫本地化GlobalCupertinoLocalizations.delegate, // Cupertino組件本地化],// 根據系統語言自動選擇localelocaleResolutionCallback: (locale, supportedLocales) {for (var supportedLocale in supportedLocales) {if (supportedLocale.languageCode == locale?.languageCode) {return supportedLocale;}}return supportedLocales.first; // 默認返回第一個支持的語言},home: const HomePage(),);}
}
2.3 創建多語言資源文件
創建一個抽象類定義所有翻譯鍵,并為每種語言創建實現類:
定義基礎接口
// lib/l10n/app_localizations.dart
import 'package:flutter/material.dart';abstract class AppLocalizations {static AppLocalizations of(BuildContext context) {return Localizations.of<AppLocalizations>(context, AppLocalizations)!;}static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();// 定義翻譯鍵String get appTitle;String greeting(String name);// 添加更多翻譯...
}
實現英語資源
// lib/l10n/app_localizations_en.dart
class AppLocalizationsEn extends AppLocalizations {@overrideString get appTitle => 'Flutter Internationalization';@overrideString greeting(String name) => 'Hello, $name!';
}
實現中文資源
// lib/l10n/app_localizations_zh.dart
class AppLocalizationsZh extends AppLocalizations {@overrideString get appTitle => 'Flutter 國際化';@overrideString greeting(String name) => '你好,$name!';
}
創建本地化代理
// lib/l10n/app_localizations.dart (繼續)
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {const _AppLocalizationsDelegate();@overridebool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);@overrideFuture<AppLocalizations> load(Locale locale) async {switch (locale.languageCode) {case 'en':return AppLocalizationsEn();case 'zh':return AppLocalizationsZh();default:return AppLocalizationsEn(); // 默認使用英語}}@overridebool shouldReload(_AppLocalizationsDelegate old) => false;
}
在 UI 中使用本地化字符串
// lib/home_page.dart
import 'package:flutter/material.dart';class HomePage extends StatelessWidget {const HomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {final localizations = AppLocalizations.of(context);return Scaffold(appBar: AppBar(title: Text(localizations.appTitle),),body: Center(child: Text(localizations.greeting('World')),),);}
}
3. 相機相冊調用
在 Flutter 中調用相機和相冊功能,需要使用image_picker
插件。以下是完整實現步驟:
3.1 添加依賴
在pubspec.yaml
中添加依賴:
dependencies:flutter:sdk: flutterimage_picker: ^1.0.2 # 最新版本
然后執行flutter pub get
安裝。
3.2 配置權限
iOS
在ios/Runner/Info.plist
中添加:
<key>NSCameraUsageDescription</key>
<string>應用需要訪問相機來拍攝照片</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>應用需要訪問相冊來選擇照片</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>應用需要保存照片到相冊</string>
Android
在android/app/src/main/AndroidManifest.xml
中添加:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- Android 10及以下需要 -->
3.3 實現相機和相冊功能
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';class CameraGalleryExample extends StatefulWidget {@override_CameraGalleryExampleState createState() => _CameraGalleryExampleState();
}class _CameraGalleryExampleState extends State<CameraGalleryExample> {final ImagePicker _picker = ImagePicker();XFile? _pickedImage;// 從相機拍攝照片Future<void> _takePhoto() async {try {final XFile? photo = await _picker.pickImage(source: ImageSource.camera);if (photo != null) {setState(() {_pickedImage = photo;});}} catch (e) {print('Error taking photo: $e');// 顯示錯誤提示ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('拍照失敗: $e')),);}}// 從相冊選擇照片Future<void> _selectFromGallery() async {try {final XFile? image = await _picker.pickImage(source: ImageSource.gallery);if (image != null) {setState(() {_pickedImage = image;});}} catch (e) {print('Error selecting image: $e');// 顯示錯誤提示ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('選擇圖片失敗: $e')),);}}
}
3.4 高級功能
拍攝視頻
Future<void> _recordVideo() async {final XFile? video = await _picker.pickVideo(source: ImageSource.camera);if (video != null) {// 處理視頻}
}
多選圖片
Future<void> _selectMultipleImages() async {final List<XFile>? images = await _picker.pickMultiImage();if (images != null && images.isNotEmpty) {// 處理多張圖片}
}
五、Flutter 調用原生代碼
在 Flutter 中調用原生代碼(如 Android 的 Java/Kotlin 或 iOS 的 Swift/Objective-C)需要使用 平臺通道(Platform Channel)。以下是主要實現方式:
基本原理
MethodChannel 是 Flutter 與原生平臺(Android、iOS)之間進行通信的一種機制,屬于 Flutter 提供的三種通信通道之一(另外兩種是 BasicMessageChannel 和 EventChannel)。它允許 Flutter 代碼調用原生代碼的方法,也允許原生代碼調用 Flutter 代碼的方法,實現雙向通信。
實現步驟
在 Flutter 端創建通道
import 'package:flutter/services.dart';class DeviceInfo {static const MethodChannel _channel = MethodChannel('com.example.device_info');// 獲取設備信息static Future<Map<String, dynamic>> getInfo() async {try {final Map<dynamic, dynamic> result = await _channel.invokeMethod('getDeviceInfo');return Map<String, dynamic>.from(result);} on PlatformException catch (e) {throw Exception('Failed to get device info: ${e.message}');}}Future<void> _fetchDeviceInfo() async {try {final info = await DeviceInfo.getInfo();setState(() {_deviceInfo = info;});} catch (e) {print('Error: $e');}}
}
在 Android 端實現(Kotlin)
package com.example.device_infoimport android.os.Build
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Resultclass DeviceInfoPlugin : FlutterPlugin, MethodCallHandler {private lateinit var channel: MethodChanneloverride fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {channel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.example.device_info")channel.setMethodCallHandler(this)}override fun onMethodCall(call: MethodCall, result: Result) {if (call.method == "getDeviceInfo") {val deviceInfo = mutableMapOf<String, Any>()// 添加設備信息deviceInfo["model"] = Build.MODELdeviceInfo["brand"] = Build.BRANDdeviceInfo["device"] = Build.DEVICEdeviceInfo["androidVersion"] = Build.VERSION.RELEASEdeviceInfo["sdkInt"] = Build.VERSION.SDK_INTresult.success(deviceInfo)} else {result.notImplemented()}}override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {channel.setMethodCallHandler(null)}
}package com.example.my_appimport io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import com.example.device_info.DeviceInfoPluginclass MainActivity : FlutterActivity() {override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)// 注冊插件flutterEngine.plugins.add(DeviceInfoPlugin())}
}
在 iOS 端實現(Swift)
import Flutter
import UIKitpublic class DeviceInfoPlugin: NSObject, FlutterPlugin {public static func register(with registrar: FlutterPluginRegistrar) {let channel = FlutterMethodChannel(name: "com.example.device_info",binaryMessenger: registrar.messenger())let instance = DeviceInfoPlugin()registrar.addMethodCallDelegate(instance, channel: channel)}public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {if call.method == "getDeviceInfo" {let device = UIDevice.currentlet info = ["model": device.model,"systemName": device.systemName,"systemVersion": device.systemVersion,"localizedModel": device.localizedModel,"name": device.name]result(info)} else {result(FlutterMethodNotImplemented)}}
}import UIKit
import Flutter@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {// 注冊插件GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}
}