美文网首页Flutter
Flutter——iOS项目混合flutter界面

Flutter——iOS项目混合flutter界面

作者: Lucky_Blue | 来源:发表于2021-07-02 14:20 被阅读0次

    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,channelmine, 他们分别加载了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_pathflutter项目的路径。
    执行pod install命令将Flutter SDKFlutter 代码 引入到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())
        }
    }
    

    相关文章

      网友评论

        本文标题:Flutter——iOS项目混合flutter界面

        本文链接:https://www.haomeiwen.com/subject/ujpihltx.html