flutter插件基礎(chǔ)之調(diào)用原生界面和flutter組件互相顯示功能(四)

前幾篇我們對flutter中的數(shù)據(jù)的傳遞層MethodChannel和監(jiān)聽響應(yīng)層EventChannel進行了全面的介紹和案例展示,本篇

開始講解flutter中如何顯示原生View,如Android 中的AndroidView的顯示和iOS中的UiKitView的顯示過程

像小孩一樣愉快的嗨起來.jpg

來吧,開始~~~展示!

四.flutter代碼中顯示原生View

1.顯示原生View的原理說明

1.1.AndroidView和UiKitView

顧名思義,flutter為了兼容原生的安卓View在flutter中顯示用AndroidView來統(tǒng)一替代所有需要顯示在flutter中的安卓view,iOS同理用的是UiKitView,簡單來說,這里的AndroidView和UiKitView相當(dāng)于是原生的一個小倉庫,所有的原生view都必須轉(zhuǎn)換為flutter對應(yīng)的AndroidView或UiKitView,至于具體的比如UiKitView有什么功能,比如UILable,UIButton則依賴于原生自身的特性決定其功能。

1.2.唯一標(biāo)識key值的設(shè)定

同前面我們講的MethodChannel和EventChannel調(diào)用機制,即通過唯一標(biāo)識符在App啟動頁或者原生插件頁中一開始進行相應(yīng)的注冊操作,然后在flutter中對其綁定同樣的key,如此可根據(jù)key的一致性,來找到原生和flutter的調(diào)用入口,同理這里的原生View展示在flutter的流程也需要保持唯一標(biāo)識key的統(tǒng)一。

如下所示為flutter代碼中對安卓和iOS設(shè)置的key值為native_view_show字符標(biāo)記。

**const** String viewType = **'native_view_show'**;

*// print("tempcreationParams = $tempcreationParams");*

**return** Container(

 width: ScreenUtils.*getScreeenWidth*(context),

 height: ScreenUtils.*getScreeenHeidth*(context),

 alignment: Alignment.*center*,

 color: Colors.*white*,

 child: defaultTargetPlatform == TargetPlatform.**android** ? AndroidView(

 viewType: viewType,

 layoutDirection: TextDirection.**ltr**,

 creationParams: {

 **"key"**: **"~~native-android"**,

 },

 creationParamsCodec: **const** StandardMessageCodec(),

 ) : UiKitView(

 viewType: viewType,

 layoutDirection: TextDirection.**ltr**,

 creationParams: {

 **"key"**: **"~~native-iOS"**,

 },

 creationParamsCodec: **const** StandardMessageCodec(),

 ),

);

如下為以安卓為例的原生類FlutterPluginDemo2Plugin.java中加入需要注冊原生界面時標(biāo)記該key的代碼如下所示,在頁面啟動頁的onAttachedToEngine 方法中

*//* 注冊原生插件類

flutterPluginBinding

 .getPlatformViewRegistry()

 .registerViewFactory(**"native_view_show"**, **new** NativeViewFactory());

1.3.原生端的工廠類創(chuàng)建

同上所示,在一開始注冊原生插件的時候,需要創(chuàng)建NativeViewFactory.java類,繼承自PlatformViewFactory類,在該類里面初始化創(chuàng)建NativeView.java類,繼承自PlatformView類,之后在工廠類里面創(chuàng)建NativeView.java類,在NativeView.java類里面對要展示的view進行基本初始化和功能操作。

如此即可實現(xiàn)最終在如安卓的NativeView.java中顯示的view功能顯示到flutter代碼中。

2.同原生代碼交互示例

在前面我們對flutter中顯示原生的原理進行研究說明后,接下來我們將以最簡單的原生組件如何順利展示在flutter中,進行案例講解。

那么,首先上場的是安卓端同flutter的交互展示。

2.1.安卓的顯示與傳值

2.1.1.Flutter端

在example/lib/show_native_page.dart類中在build方法中返回 AndroidView 代碼如下所示

AndroidView(

 viewType: viewType,

 layoutDirection: TextDirection.**ltr**,

 creationParams: {

 **"key"**: **"~~native-android"**,

 },

 creationParamsCodec: **const** StandardMessageCodec(),

)

其中這里的viewType是定義同安卓交互的唯一字符串標(biāo)識如下

**const** String viewType = **'native_view_show'**;

2.1.2.Native(Android)端

1.在原生安卓端的FlutterPluginDemo2Plugin.java,類中的onAttachedToEngine方法中提前注冊好原生插件NativeViewFactory工廠類;

*//* 注冊原生插件類

flutterPluginBinding

 .getPlatformViewRegistry()

 .registerViewFactory(**"native_view_show"**, **new** NativeViewFactory());

2.工廠類NativeViewFactory.java中初始化加入NativeView.java類

代碼如下所示:

**class** NativeViewFactory **extends** PlatformViewFactory {

 NativeViewFactory() {

 **super**(StandardMessageCodec.INSTANCE);

 }

 @NonNull

 @Override

 **public** PlatformView create(@NonNull Context context, **int** id, @Nullable Object args) {

 **final** Map<String, Object> creationParams = (Map<String, Object>) args;

 Log.d(**"creationParams"**, creationParams.toString());

*// System.out.print(creationParams);*

**return new** NativeView(context, id, creationParams);

 }

}

3.在NativeView.java類中自定義安卓的view(如示例所示為一段textView對象居中顯示效果),

安卓View顯示到flutter.jpeg

如此就可以通過以上方法把安卓的TextView正確顯示在flutter的界面上,實現(xiàn)我們的目標(biāo)。

2.2.iOS的顯示與傳值

2.2.1.Flutter端

同安卓端所示,在 example/lib/show_native_page.dart類中在build方法中返回 UiKitView 代碼所示

UiKitView(

 viewType: viewType,

 layoutDirection: TextDirection.**ltr**,

 creationParams: {

 **"key"**: **"~~native-iOS"**,

 },

 creationParamsCodec: **const** StandardMessageCodec(),

)

2.2.2.Native(iOS)端

同安卓端類似,iOS的原生端流程可以簡單概括為,

工廠類的注冊——>工廠類的初始化創(chuàng)建——>原生iOSView的展示

1.工廠類的注冊

在iOS的 FlutterPluginDemo2Plugin.m類的 registerWithRegistrar方法中提前注冊好工廠類FlutterNativeFactory,保證是同flutter的唯一標(biāo)識字符串相同,如下為native_view_show

FlutterNativeFactory* factory =

 [[FlutterNativeFactory alloc] initWithMessenger:registrar.messenger];

 [registrar registerViewFactory:factory withId:**@"native_view_show"**];

2.工廠類的初始化創(chuàng)建
在FlutterNativeFactory.h類中遵循FlutterPlatformViewFactory協(xié)議,實現(xiàn)其createWithFrame方法,如下所示

- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame

 viewIdentifier:(int64_t)viewId

 arguments:(id **_Nullable**)args {

 **return** [[FlutterNativeView alloc] initWithFrame:frame

 viewIdentifier:viewId

 arguments:args

 binaryMessenger:_messenger];

}

在FlutterNativeFactory.m類中設(shè)置初始化入口initWithMessenger方法,供FlutterPluginDemo2Plugin.m類使用

3.原生iOS的View的展示

在原生的FlutterNativeView類中的initWithFrame方法中初始化iOS的view,通過以上的流程順利展示在flutter界面上

- (instancetype)initWithFrame:(CGRect)frame

 viewIdentifier:(int64_t)viewId

 arguments:(id **_Nullable**)args

 binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {

 **if** (self = [super init]) {

 _view = [[UIView alloc] init];

*// double kScreenW =* [*UIScreen mainScreen*]*.bounds.size.width;*

*// double kScreenH =* [*UIScreen mainScreen*]*.bounds.size.height;*

_view.frame = CGRectMake(0, 200, 200, 200);

 _view.backgroundColor = [UIColor redColor];

 NSLog(**@"args = %@"**,args);

 **if** ([args isKindOfClass:[NSDictionary **class**]]) {

 NSString *key = args[**@"key"**];

 NSLog(**@"key = %@"**);

 _nameLable.text = [NSString stringWithFormat:**@"%@%@%@"**,**@"我是"**,key,**@"的UILabel"**];

 }

 [_view addSubview:self.nameLable];

 }

 **return** self;

}

3.注意事項細節(jié)

3.1.唯一標(biāo)識key的統(tǒng)一

雖然有點啰嗦,但仍需要再次說明,即在example/lib/show_native_page.dart類中設(shè)置viewType的值

**const** String viewType = **'native_view_show'**;

要和如下所示(以安卓為例)的FlutterPluginDemo2Plugin.java類中的onAttachedToEngine方法注冊的插件view工廠類的key保持一致

*//* 注冊原生插件類

flutterPluginBinding

 .getPlatformViewRegistry()

 .registerViewFactory(**"native_view_show"**, **new** NativeViewFactory());

3.2.傳值問題

如下所示為安卓的AndroidView中的creationParams屬性可以設(shè)置flutter要傳遞給原生的內(nèi)容,在經(jīng)過層層傳遞后可以實現(xiàn)在安卓的NativeView.java類的構(gòu)造方法中獲取到傳遞的內(nèi)容為creationParams對象,從而展示在原生的TextView對象身上。

NativeView(@NonNull Context context, **int** id, @Nullable Map<String, Object> creationParams) {

 String value = creationParams.get(**"key"**).toString();

 **textView** = **new** TextView(context);

 **textView**.setTextSize(30);

 **textView**.setBackgroundColor(Color.rgb(255, 255, 255));

 **textView**.setGravity(Gravity.CENTER);

 **textView**.setText(**"show Android view (原生接收到的值為: "** + value + **")"**);

}

3.3.iOS原生界面展示細節(jié)說明

需要注意的是在iOS中的最外層界面展示尺寸方面,僅對位置定義有用,對尺寸設(shè)置是沒用的,會默認(rèn)鋪滿剩余空間,所以如下所示為安卓的最外層界面展示內(nèi)容:

_view.center = CGPointMake(200, 150);

 _view.bounds = CGRectMake(0, 0, 100, 100);

 _view.backgroundColor = [UIColor redColor];

而對_view的subview如nameLable并沒有影響,可以正常按照iOS的規(guī)則進行相關(guān)設(shè)置操作

 **self**.nameLable.frame = CGRectMake(0, 100, 200, 50);

 **self**.nameLable.backgroundColor = [UIColor blueColor];

 [_view addSubview:**self**.nameLable];

簡而言之,即為設(shè)置原生最外層尺寸時,僅設(shè)置其定位位置,如frame的前2項x和y或者是center對象,而對其尺寸方面的設(shè)置是無效的,因為它會默認(rèn)鋪滿剩余尺寸,但是對該view的子view設(shè)置尺寸按照正常的iOS規(guī)則是可以生效的。

這是按照上面設(shè)置父View和子View后的效果如下所示,安卓是不是遵循同樣的規(guī)則,還請小伙伴們自行驗證哈。

iOSView在flutter上的顯示.png

好了,經(jīng)過前面的研究和分析,我們對flutter同原生的數(shù)據(jù)層交互的MethodChannel,EventChannel,以及界面層交互的AndroidView 和 UiKitView的基礎(chǔ)使用基本掌握,并且對二者交互的原理得到進一步的了解,這里附上在此系列中寫的所有代碼的一個小案例,以餉食者!

Flutter同原生交互案例展示:flutter同原生交互Demo示例

下一篇我們將逐步嘗試從簡單編寫一個小插件,小插件的本地,遠程發(fā)布,以及如何使用的流程進行整體的說明,從而讓大家都能編寫好自己的小插件,盡可能的解決更多flutter解決不了的原生問題,提供開發(fā)速度。
flutter插件基礎(chǔ)之調(diào)用EventChannel的簡單使用(三)

好了,本篇完~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容