天天看點

Flutter與原生iOS互動

從Flutter項目跳轉到iOS原生界面

    • Flutter官網鎮樓
    • 前言
    • Flutter 代碼
    • iOS原生代碼

Flutter官網鎮樓

Flutter官網

前言

從Flutter項目跳轉到iOS原生界面,支援push和present方式,由于時間比較緊,是以隻總結了頁面跳轉,後續會完善flutter與原生之間的互動傳值。話不多說,直接上代碼(本人是iOS開發,是以Android 端暫時沒有實作)

Flutter 代碼

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter native iOS'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

/*<與原生互動信号通道 >*/
const methodChannel = const MethodChannel('flutter_native_ios');

class _MyHomePageState extends State<MyHomePage> {
  //封裝 Flutter 向 原生中 發送消息 的方法
  //method 為方法辨別
  //arguments 為參數
  static Future<dynamic> tokNative(String method, {Map arguments}) async {
    if (arguments == null) {
      //無參數發送消息
      return await methodChannel.invokeMethod(method);
    } else {
      //有參數發送消息
      return await methodChannel.invokeMethod(method, arguments);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new ListTile(
              title: new Text('flutter與原生互動,(push)'),
              trailing: FlatButton(
                  onPressed: () {
                    tokNative('flutter_push_to_ios')
                      ..then((result) {
                        print('$result');
                      });
                    print('push');
                  },
                  child: Icon(
                    Icons.arrow_forward_ios,
                    size: 20,
                  )),
            ),
            new ListTile(
              title: new Text('flutter與原生互動,(present)'),
              trailing: FlatButton(
                  onPressed: () {
                    tokNative('flutter_present_to_ios')
                      ..then((result) {
                        print('$result');
                      });
                    print('present');
                  },
                  child: Icon(
                    Icons.arrow_forward_ios,
                    size: 20,
                  )),
            ),
          ],
        ),
      ),
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
           

iOS原生代碼

一、在iOS項目裡建立跟控制器,繼承于FlutterViewController

#import "MainViewController.h"
#include "GeneratedPluginRegistrant.h"
#import "TestViewController.h"

/** 信号通道,須與flutter裡一緻*/
#define flutterMethodChannel  @"flutter_native_ios"
/** 互動方法字段名,須與flutter裡一緻*/
#define flutterMethodPush  @"flutter_push_to_ios"
#define flutterMethodPresent  @"flutter_present_to_ios"

@interface MainViewController ()

@property(nonatomic,strong) FlutterMethodChannel* methodChannel;

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self methodChannelFunction];
}
- (void)methodChannelFunction {
    //建立 FlutterMethodChannel
    self.methodChannel = [FlutterMethodChannel
                          methodChannelWithName:flutterMethodChannel binaryMessenger:self];
    //設定監聽
    [self.methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
        // TODO
        NSString *method=call.method;
        if ([method isEqualToString:flutterMethodPush]) {
            TestViewController *vc = [[TestViewController alloc] init];
            [self.navigationController pushViewController:vc animated:YES];
            //此方法隻能調用一次
            result(@"push傳回到flutter");
        }else if ([method isEqualToString:flutterMethodPresent]) {
            TestViewController *vc = [[TestViewController alloc] init];
            [self presentViewController:vc animated:NO completion:nil];
            //此方法隻能調用一次
            result(@"present傳回到flutter");
        }
        
    }];
    [GeneratedPluginRegistrant registerWithRegistry:self];
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES];
}

-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self.navigationController setNavigationBarHidden:NO];
}

@end

           

二、APPDelegate實作方式

#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "MainViewController.h"
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    /** 設定主要制器繼承FlutterViewController*/
    MainViewController * VC = [[MainViewController alloc]init];
    UINavigationController * NVC = [[UINavigationController alloc]initWithRootViewController:VC];
    [self.window setRootViewController:NVC];
    /** flutter插件通道代理*/
  [GeneratedPluginRegistrant registerWithRegistry:self];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
           

三、你需要跳轉的控制器,普通控制器,不需要繼承FlutterViewController

#import "TestViewController.h"

@interface TestViewController ()

@end

@implementation TestViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
    
}
-(void)initUI{
    
    [self.view setBackgroundColor:[UIColor whiteColor]];
    UIButton * btn =[UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(20, 50, 50, 20);
    [btn setTitle:@"傳回" forState:UIControlStateNormal];
    [btn setBackgroundColor:[UIColor grayColor]];
    [btn addTarget:self action:@selector(backEvent) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];    
    
}
-(void)backEvent{
    [self dismissViewControllerAnimated:YES completion:nil];
}

@end