2018年一直在使用 flutter 寫專案,從0。2。0開始到現在1。0版本的釋出,終於開始慢慢的爬出坑位了,但是因為部分控制元件感覺還是不如原生控制元件好用,一直在摸索怎麼將原生view 可以放在 flutter 中並且不會遮擋住 flutter 的 widget。終於,看到官網提供了 PlatformView部件,因為我本身是一名 iOS 開發人員,這裡只提供 iOS 的教程,Android 開發教程在這裡。
什麼是 PlatformView?
PlatformView是 flutter 官方提供的一個可以嵌入 Android 和 iOS 平臺原生 view 的小部件。
在我們實際開發中,我們遇到一些 flutter 官方沒有提供的外掛可以自己建立編寫外掛來實現部分功能,但是原生View在 flutter 中會遮擋住flutter 中的小部件,比如你想使用高德地圖sdk、影片播放器、直播等原生控制元件,就無法很好的與 flutter 專案結合。
之前知道flutter 給 Android(
google 的親兒子
)提供了 AndroidView可以實現將 view 存放到部件中,教程也不少,無奈,iOS (
畢竟不是親的
)在網上使用 UiKitView的教程太少,目前就只看到日本的一個作者用 swift寫的 教程,終於有了可以參考的 Demo,下面我就用 Object-C 來說一下教程:
製作外掛
我們需要建立一個 專案外掛,我這裡使用 預設的 Object-C和 Java語言。Plugin
activity_indicator。dart
首先,我將建立一個StatefulWidget類,在class下顯示本機檢視。使用檔名activity_indicator。dart編寫以下程式碼。
import ‘package:flutter/foundation。dart’;import ‘package:flutter/material。dart’;import ‘package:flutter/services。dart’;typedef void UIActivityIndicatorWidgetCreatedCallback(ActivityIndicatorController controller);class ActivityIndicatorController { ActivityIndicatorController。_(int id) : _channel = MethodChannel(‘plugins/activity_indicator_$id’); final MethodChannel _channel; Future
呼叫 iOS檢視
UIKitView用於呼叫iOS檢視,如下所示。對於指定的引數,viewType用於確定本機端的目標View的返回。對於Android,我們使用AndroidView但指定viewType不會更改。
此外,onPlatformViewCreated可以將ActivityIndicatorController與UIActivityIndicator小部件一起使用。要將引數傳遞給本機端,請使用creationParams。
Widget build(BuildContext context) { // TODO: implement build if(defaultTargetPlatform == TargetPlatform。iOS){ return UiKitView( viewType: “plugins/activity_indicator”, onPlatformViewCreated:_onPlatformViewCreated, creationParams:
從 Flutter 執行原生程式碼
使用MethodChannel從Flutter執行本機程式碼。這也會編寫接收MethodChannel和invokeMethod引數的程式碼,並在本機端執行相應的處理。這次實現它,以便可以透過ActivityIndicatorController執行本機程式碼。
class ActivityIndicatorController { ActivityIndicatorController。_(int id) : _channel = MethodChannel(‘plugins/activity_indicator_$id’); final MethodChannel _channel; Future
main。dart
接下來,編輯example / main。dart並建立一個螢幕。我將使用我之前建立的UIActivityIndicator小部件。
import ‘package:flutter/material。dart’;import ‘dart:async’;import ‘package:flutter/services。dart’;import ‘package:activity_indicator/activity_indicator。dart’;void main() => runApp(MaterialApp( home: ActivityIndicatorExample(),));class ActivityIndicatorExample extends StatelessWidget{ ActivityIndicatorController controller; void _onActivityIndicatorControllerCreated(ActivityIndicatorController _controller){ controller = _controller; } @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: AppBar(title: const Text(“載入測試”),), body: Stack( alignment: Alignment。bottomCenter, children:
iOS 端實現
FlutterActivityIndicator。h
新建類,提供FlutterPlatformView和FlutterPlatformViewFactory協議
#import
從 Flutter 執行原生程式碼
要從Flutter端執行本機程式碼,可以按如下方式使用MethodChannel。它產生以前MethodChannel,當您從ActivityIndicatorController時,InvokeMethod,onMethodCall被呼叫,所以你遇到在引數中指定的字串,以及執行過程中看到它的價值。
_viewId = viewId; NSString* channelName = [NSString stringWithFormat:@“plugins/activity_indicator_%lld”, viewId];_channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger];__weak __typeof__(self) weakSelf = self;[_channel setMethodCallHandler:^(FlutterMethodCall * call, FlutterResult result) { [weakSelf onMethodCall:call result:result];}];-(void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result{ if ([[call method] isEqualToString:@“start”]) { [_indicator startAnimating]; }else if ([[call method] isEqualToString:@“stop”]){ [_indicator stopAnimating]; } else { result(FlutterMethodNotImplemented); }}
將引數從 Flutter 傳遞到 iOS
由於Flutter端的creationParams指定的值是args,因此將其轉換為型別並設定為UIActivityIndicatorView的屬性。
NSDictionary *dic = args;NSString *hexColor = dic[@“hexColor”]; bool hidesWhenStopped = [dic[@“hidesWhenStopped”] boolValue]; _indicator = [[UIActivityIndicatorView alloc]init];_indicator。activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;_indicator。color = [UIColor colorWithHexString:hexColor];_indicator。hidesWhenStopped = hidesWhenStopped;
ActivityIndicatorPlugin。m
自動生成檔案中,只需要這樣寫
#import “ActivityIndicatorPlugin。h”#import “FlutterActivityIndicator。h”@implementation ActivityIndicatorPlugin+ (void)registerWithRegistrar:(NSObject
要保證你的viewId指定的字串與你 flutter 端程式碼的ViewType指定的字串相匹配
最重要的一步操作
要在你的 info。plist中新增
要求必須這樣設定https://github。com/flutter/flutter/issues/19030#issuecomment-437534853
演示
演示 Demo。gif
Demo 地址
https://github。com/rongshuizhou/activity_indicator。git