Flutter快速上手,入门教程_flutter教程
目录
一、参考文档
二、准备工作
下载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.cnexport 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 runflutter -d allflutter -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); @override Widget build(BuildContext context) { return Consumer( 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); @override Widget build(BuildContext context) { final themeProvider = Provider.of(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: flutter flutter_localizations: sdk: flutter intl: ^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); @override Widget 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组件本地化 ], // 根据系统语言自动选择locale localeResolutionCallback: (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.dartimport \'package:flutter/material.dart\';abstract class AppLocalizations { static AppLocalizations of(BuildContext context) { return Localizations.of(context, AppLocalizations)!; } static const LocalizationsDelegate delegate = _AppLocalizationsDelegate(); // 定义翻译键 String get appTitle; String greeting(String name); // 添加更多翻译...}
实现英语资源
// lib/l10n/app_localizations_en.dartclass AppLocalizationsEn extends AppLocalizations { @override String get appTitle => \'Flutter Internationalization\'; @override String greeting(String name) => \'Hello, $name!\';}
实现中文资源
// lib/l10n/app_localizations_zh.dartclass AppLocalizationsZh extends AppLocalizations { @override String get appTitle => \'Flutter 国际化\'; @override String greeting(String name) => \'你好,$name!\';}
创建本地化代理
// lib/l10n/app_localizations.dart (继续)class _AppLocalizationsDelegate extends LocalizationsDelegate { const _AppLocalizationsDelegate(); @override bool isSupported(Locale locale) => [\'en\', \'zh\'].contains(locale.languageCode); @override Future load(Locale locale) async { switch (locale.languageCode) { case \'en\': return AppLocalizationsEn(); case \'zh\': return AppLocalizationsZh(); default: return AppLocalizationsEn(); // 默认使用英语 } } @override bool shouldReload(_AppLocalizationsDelegate old) => false;}
在 UI 中使用本地化字符串
// lib/home_page.dartimport \'package:flutter/material.dart\';class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget 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: flutter image_picker: ^1.0.2 # 最新版本
然后执行flutter pub get
安装。
3.2 配置权限
iOS
在ios/Runner/Info.plist
中添加:
NSCameraUsageDescription应用需要访问相机来拍摄照片NSPhotoLibraryUsageDescription应用需要访问相册来选择照片NSPhotoLibraryAddUsageDescription应用需要保存照片到相册
Android
在android/app/src/main/AndroidManifest.xml
中添加:
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 { final ImagePicker _picker = ImagePicker(); XFile? _pickedImage; // 从相机拍摄照片 Future _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 _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 _recordVideo() async { final XFile? video = await _picker.pickVideo(source: ImageSource.camera); if (video != null) { // 处理视频 }}
多选图片
Future _selectMultipleImages() async { final List? 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> getInfo() async { try { final Map result = await _channel.invokeMethod(\'getDeviceInfo\'); return Map.from(result); } on PlatformException catch (e) { throw Exception(\'Failed to get device info: ${e.message}\'); } } Future _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.Buildimport io.flutter.embedding.engine.plugins.FlutterPluginimport io.flutter.plugin.common.MethodCallimport io.flutter.plugin.common.MethodChannelimport io.flutter.plugin.common.MethodChannel.MethodCallHandlerimport io.flutter.plugin.common.MethodChannel.Resultclass DeviceInfoPlugin : FlutterPlugin, MethodCallHandler { private lateinit var channel: MethodChannel override 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() // 添加设备信息 deviceInfo[\"model\"] = Build.MODEL deviceInfo[\"brand\"] = Build.BRAND deviceInfo[\"device\"] = Build.DEVICE deviceInfo[\"androidVersion\"] = Build.VERSION.RELEASE deviceInfo[\"sdkInt\"] = Build.VERSION.SDK_INT result.success(deviceInfo) } else { result.notImplemented() } } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler(null) }}package com.example.my_appimport io.flutter.embedding.android.FlutterActivityimport io.flutter.embedding.engine.FlutterEngineimport com.example.device_info.DeviceInfoPluginclass MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) // 注册插件 flutterEngine.plugins.add(DeviceInfoPlugin()) }}
在 iOS 端实现(Swift)
import Flutterimport 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.current let info = [ \"model\": device.model, \"systemName\": device.systemName, \"systemVersion\": device.systemVersion, \"localizedModel\": device.localizedModel, \"name\": device.name ] result(info) } else { result(FlutterMethodNotImplemented) } }}import UIKitimport 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) }}