Flutter——iOS项目混合flutter界面
2021-07-02 本文已影响0人
Lucky_Blue
1.创建flutter module
image.png
方式一
cd ~/Desktop/Flutter
flutter create --template module video_flutter
方式二
Android Studio
注意⚠️创建的module最好和iOS原生的项目在同一个层级的文件目录,因为iOS项目需要引用Flutter项目中的文件和库。
2.编写flutter
代码
@pragma('vm:entry-point')
void main() {
runApp(MainApp());
}
@pragma('vm:entry-point')
void channel() {
runApp(ChannelApp());
}
@pragma('vm:entry-point')
void mine() {
runApp(MineApp());
}
image.png
1.首页定义了三个函数main
,channel
和mine
, 他们分别加载了MainApp()
,ChannelApp()
和MineApp()
,也可以直接理解为三个模块,他们是相互独立的。
2.由于main()
函数是提供给Flutter Engine
层调用,Dart
中没有地方引用,预处理命令@pragma('vm:entry-point')
是为了告诉编译器不要去除这个未引用的方法。
2.main_page.dart
代码
由于其他两个模块代码也是类似的,就以main_page.dart
为例。
import 'package:flutter/material.dart';
class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "首页模块",
theme: ThemeData(primarySwatch: Colors.blue),
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MainPageState();
}
}
class MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Scrollbar(
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
childAspectRatio: 6 / 3,
),
children: List.generate(100, (index) {
return getItem(index);
}),
),
),
),
);
}
}
/// 获取子项目
Widget getItem(int index) {
return Container(
decoration: BoxDecoration(color: Colors.red),
);
}
可以看到跟普通的Flutter project
的代码没有任何差别。
3.iOS项目引入Flutter模块
首先打开iOS
项目找到Podfile
文件,如果没有的话就新建一个。
#1. 找到flutter module 的目录
flutter_application_path = '../video_flutter'
#2. 找到flutter module 的目录中的/.ios/Flutter/podhelper.rb文件
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'Video_iOS' do
use_frameworks!
#3. 执行podhelper.rb中的install_all_flutter_pods方法
install_all_flutter_pods(flutter_application_path)
end
flutter_application_path
是flutter
项目的路径。
执行pod install
命令将Flutter SDK
和 Flutter
代码 引入到iOS
项目中。
在AppDelegate
创建一个FlutterEngineGroup
用来管理多个FlutterEngine
, 让他们共享资源等功能。
import UIKit
import Flutter
import FlutterPluginRegistrant
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var engineGroup = FlutterEngineGroup(name: "video_flutter", project: nil)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
创建一个继承于FlutterViewController
的子类,子类会根据传过来的entrypoint
初始化一个FlutterEngine
,这个FlutterEngine
的加载入口是main.dart
文件中entrypoint
函数,然后FlutterViewController
子类持有这个FlutterEngine
。
import Flutter
class JHFlutterViewController : FlutterViewController{
init(withEntrypoint entrypoint : String?) {
let appDelegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
let newEngine = appDelegate.engineGroup.makeEngine(withEntrypoint: entrypoint, libraryURI: nil)
super.init(engine: newEngine, nibName: nil, bundle: nil)
}
required convenience init(coder aDecoder: NSCoder) {
self.init(withEntrypoint : nil)
}
}
接下来是UIViewController
加载JHFlutterViewController
import UIKit
class MainViewController: UIViewController {
// 1. 懒加载 main.dart 中的main入口函数对应的Flutter App
private lazy var subFlutterVC : JHFlutterViewController = JHFlutterViewController(withEntrypoint: nil)
override func viewDidLoad() {
// 2. 添加FlutterViewController
addChild(subFlutterVC)
let safeFrame = self.view.safeAreaLayoutGuide.layoutFrame
subFlutterVC.view.frame = safeFrame;
self.view.addSubview(subFlutterVC.view)
subFlutterVC.didMove(toParent: self)
}
}
到现在三个Flutter module
已经被集成到了我们的iOS
项目中了。如果在Flutter module
中用了插件来实现的,我们需要把插件统一注册到Flutter Engine
中,在JHFlutterViewController
子类中修改如下
import Flutter
import FlutterPluginRegistrant
class JHFlutterViewController : FlutterViewController{
init(withEntrypoint entrypoint : String?) {
let appDelegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
let newEngine = appDelegate.engineGroup.makeEngine(withEntrypoint: entrypoint, libraryURI: nil)
super.init(engine: newEngine, nibName: nil, bundle: nil)
}
required convenience init(coder aDecoder: NSCoder) {
self.init(withEntrypoint : nil)
}
override func viewDidLoad() {
super.viewDidLoad()
GeneratedPluginRegistrant.register(with: self.pluginRegistry())
}
}