From 4df19d79b0da15382c98198d7108ab2aea50388a Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Mon, 20 May 2024 17:00:23 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9PlatformView=E7=9B=B8?= =?UTF-8?q?=E5=85=B3md=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- ...07\346\215\242\346\214\207\345\257\274.md" | 26 ++ ohos/docs/04_development/README.md | 1 + ...25\344\275\277\347\224\250PlatformView.md" | 275 +++++++++++++----- 3 files changed, 222 insertions(+), 80 deletions(-) create mode 100644 "ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" diff --git "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" new file mode 100644 index 00000000..71cb171c --- /dev/null +++ "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" @@ -0,0 +1,26 @@ +## PlatformView同层渲染方案适配切换指导 + + + + +## PlatformView旧方案 + +### 简述 +在Flutter适配层定义DynamicView和DVModel,通过PlatformViewChannel通道获取到的参数生成对应DVModel,并基于该DVModel和DynamicView渲染应用OHOS侧定义的OHOS原生组件 +FlutterPage中,对接Xcomponent的FlutterView置于底层,而DynamicView实现的PlatformView置于上层 + +### 缺陷 +1. PlatformView覆盖在FlutterView上面出现遮挡问题 +2. FlutterView和PlatformView动画不一致 + + + + +## PlatformView新方案 + +### 简述 +采用NodeContainer同层渲染功能,将原生平台组件的纹理导出注册到Flutter Engine,由Flutter统一渲染 + +### 区别 +1. 新方案由Flutter统一渲染,不会出现PlatformView和FlutterView不一致、相互影响的问题 +2. 由json定义改为更形象的Component组件定义;开发者可通过OHOS侧使用Component组件方式自定义页面样式组件,方便易懂,符合OHOS原生应用开发习惯 \ No newline at end of file diff --git a/ohos/docs/04_development/README.md b/ohos/docs/04_development/README.md index f3f09286..85fd819e 100644 --- a/ohos/docs/04_development/README.md +++ b/ohos/docs/04_development/README.md @@ -14,6 +14,7 @@ 1. [Flutter OHOS外接纹理适配简介.md](./Flutter%20OHOS外接纹理适配简介.md) 2. [如何使用 FlutterEngineGroup](./如何使用%20FlutterEngineGroup.md) 3. [如何使用PlatformView](./如何使用PlatformView.md) +4. [PlatformView同层渲染方案适配切换指导](./PlatformView同层渲染方案适配切换指导.md) ## 开发Flutter静态库 diff --git "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" index 4a13566a..791f2311 100644 --- "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" +++ "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" @@ -16,57 +16,114 @@ ### 一、Native侧 -1,使用 `DevEco Studio`工具打开 `platform_view_example\ohos`项目 +1. 使用 `DevEco Studio`工具打开 `platform_view_example\ohos`项目 -2,在`platform_view_example\ohos\entry\src\main\ets\`目录下实现代码 +2. 在`platform_view_example\ohos\entry\src\main\ets\entryability`目录下实现代码 -3,新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 +3. 新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 + 3.1 定义一个`Component`,用于生成OHOS侧`PlatformView` +```java +struct ButtonComponent { + @Prop params: Params + customView: CustomView = this.params.platformView as CustomView + @StorageLink('numValue') storageLink: string = "first" + @State bkColor: Color = Color.Red + + build() { + Column() { + Button("发送数据给Flutter") + .border({ width: 2, color: Color.Blue}) + .backgroundColor(this.bkColor) + .onTouch((event: TouchEvent) => { + console.log("nodeController button on touched") + }) + .onClick((event: ClickEvent) => { + this.customView.sendMessage(); + console.log("nodeController button on click") + }) + + Text(`来自Flutter的数据 : ${this.storageLink}`) + .onTouch((event: TouchEvent) => { + console.log("nodeController text on touched") + }) + + + }.alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .direction(Direction.Ltr) + .width('100%') + .height('100%') + } +} +``` + + 3.2 定义一个方法,调用自定义Component获取原生平台组件的纹理,然后通过WrappedBuilder返回出去 +```java +@Builder +function ButtonBuilder(params: Params) { + ButtonComponent({ params: params }) + .backgroundColor(Color.Yellow) + // .width('50%').height('50%') +} +``` + 3.3 在Customview类里面设置具体通道及方法,同时返回`WrappedBuilder`导出原生平台组件的纹理到`engine` ```java +import MethodChannel, { + MethodCallHandler, + MethodResult + } from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; +import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; import common from '@ohos.app.ability.common'; +import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec'; import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; -import PlatformView from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'; -import MethodChannel, { - MethodCallHandler, - MethodResult -} from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodChannel'; -import { StandardMethodCodec } from '@ohos/flutter_ohos'; + import { DVModel } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView'; -import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/BinaryMessenger'; +import { createDVModelFromJson } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson'; +@Observed export class CustomView extends PlatformView implements MethodCallHandler { - - methodChannel: MethodChannel; - - constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) { - super(); - // 注册消息通道 - this.methodChannel = new MethodChannel(message, `channel/custom_view_${viewId}`, StandarMethodCodec.INSTANCE); - this.methodChannel.setMethodCallHandler(this); - } + numValue: string = "test"; + + methodChannel: MethodChannel; + index: number = 1; - onMethodCall(call:MethodCall,result:MethodResult):void{ - // 接收Dart侧发来的消息 - let method:string = call.method; - switch(method){ - case 'MessageFromFlutterView': - let value:ESObject = call.args; - result.success(true); - break; + constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) { + super(); + console.log("nodeController viewId:" + viewId) + // 注册消息通道 + this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE); + this.methodChannel.setMethodCallHandler(this); } - } - private sendMessage = () => { - // 向Dart侧发送消息 - this.methodChannel.invokeMethod('MessageFromNativeView','customview'); - } + onMethodCall(call: MethodCall, result: MethodResult): void { + // 接受Dart侧发来的消息 + let method: string = call.method; + let link1: SubscribedAbstractProperty = AppStorage.link('numValue'); + switch (method) { + case 'getMessageFromFlutterView': + let value: ESObject = call.args; + this.numValue = value; + link1.set(value) + console.log("nodeController receive message from dart: " + this.numValue); + result.success(true); + break; + } + } - getView(): DVModel{ - throw new Error('Method not implemented.'); - } + public sendMessage = () => { + console.log("nodeController sendMessage") + //向Dart侧发送消息 + this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ' + this.index++); + } - dispose(): void{} + getView(): WrappedBuilder<[Params]> { + return new WrappedBuilder(ButtonBuilder); + } + dispose(): void { + } } ``` @@ -85,7 +142,7 @@ export class CustomPlugin implements FlutterPlugin { onAttachedToEngine(binding: FlutterPluginBinding): void { binding.getPlatformViewRegistry()?. - registerViewFactory('native/custom_view', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); + registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); } onDetachedFromEngine(binding: FlutterPluginBinding): void {} @@ -174,27 +231,63 @@ class CustomPage extends StatefulWidget { ```dart class _CustomPageState extends State { + String receivedData = ''; CustomViewController? _controller; - Widget _getPlatformOhosView() { + void _onCustomOhosViewCreated(CustomViewController controller) { + _controller = controller; + _controller?.customDataStream.listen((data) { + //接收到来自OHOS端的数据 + setState(() { + receivedData = '来自ohos的数据:$data'; + }); + }); + } + + Widget _buildOhosView() { return Expanded( - flex: 1, child: Container( color: Colors.blueAccent.withAlpha(60), - child: OhosView( - viewType: 'native/custom_view', // 与Native侧对应view注册Plugin的viewTypeId要一致 - onPlatformViewCreated: _onPlatformViewCreated, - creationParams: const {'initParams': 'hello world'}, - creationParamsCodec: const StandardMessageCodec(), - ), + child: CustomOhosView(_onCustomOhosViewCreated), ), + flex: 1, ); } - Widget _getFlutterView() { + Widget _buildFlutterView() { return Expanded( + child: Stack( + alignment: AlignmentDirectional.bottomCenter, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + TextButton( + onPressed: () { + final randomNum = Random().nextInt(10); + _controller + ?.sendMessageToOhosView('flutter - $randomNum '); + }, + child: const Text('发送数据给ohos'), + ), + const SizedBox(height: 10), + Text(receivedData), + ], + ), + const Padding( + padding: EdgeInsets.only(bottom: 15), + child: Text( + 'Flutter - View', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), flex: 1, - child: Stack(), ); } @@ -202,29 +295,11 @@ class _CustomPageState extends State { Widget build(BuildContext context) { return Column( children: [ - _getPlatformOhosView(), - _getFlutterView(), + _buildOhosView(), + _buildFlutterView(), ], ); } - - // PlatformView创建成功回调,参数id是platform view的唯一标识符 - void _onPlatformViewCreated(int id) { - // 创建MethodChannel对象,负责收发Native侧消息,channel name要与Native侧一致 - MethodChannel channel = MethodChannel('channel/custom_view_${id}'); - - // 初始化controller - final controller = CustomViewController._(channel); - - _onCustomOhosViewCreated(controller); - } - - void _onCustomOhosViewCreated(CustomViewController controller) { - _controller = controller; - _controller?.customDataStream.listen((data) { - // 接收Native侧发来的消息 - }); - } } ``` @@ -234,33 +309,73 @@ OhosView组件就是桥接Native view的关键。 - onPlatformViewCreated:PlatformView创建成功时的回调。 - creationParams:传递给NativeView的初始化参数。 +5、实现CustomOhosView,自定义OhosView,用于dart与platform之间的通道实现 +```dart +class CustomOhosView extends StatefulWidget { + final OnViewCreated onViewCreated; + + const CustomOhosView(this.onViewCreated, {Key? key}) : super(key: key); + @override + State createState() => _CustomOhosViewState(); +} -5、新建CustomViewController,用于实现Dart侧与Native侧的交互 +class _CustomOhosViewState extends State { + late MethodChannel _channel; + + @override + Widget build(BuildContext context) { + return _getPlatformFaceView(); + } + + Widget _getPlatformFaceView() { + return OhosView( + viewType: 'com.rex.custom.ohos/customView', + onPlatformViewCreated: _onPlatformViewCreated, + creationParams: const {'initParams': 'hello world'}, + creationParamsCodec: const StandardMessageCodec(), + ); + } + + void _onPlatformViewCreated(int id) { + _channel = MethodChannel('com.rex.custom.ohos/customView$id'); + final controller = CustomViewController._( + _channel, + ); + widget.onViewCreated(controller); + } +} +``` + +6、新建CustomViewController,用于实现Dart侧与Native侧的交互 ```dart class CustomViewController { final MethodChannel _channel; final StreamController _controller = StreamController(); - CustomViewController._(this._channel) { - _channel.setMethodCallHandler((call) async { - // 接受Native侧发来的消息 - switch (call.method) { - case 'MessageFromNativeView': - final result = call.arguments as String; - _controller.sink.add(result); - break; - } - }); + CustomViewController._( + this._channel, + ) { + _channel.setMethodCallHandler( + (call) async { + switch (call.method) { + case 'getMessageFromOhosView': + // 从native端获取数据 + final result = call.arguments as String; + _controller.sink.add(result); + break; + } + }, + ); } Stream get customDataStream => _controller.stream; - // 向Native侧发送消息 + // 发送数据给native Future sendMessageToOhosView(String message) async { await _channel.invokeMethod( - 'MessageFromFlutterView', + 'getMessageFromFlutterView', message, ); } -- Gitee From 4dd4aedb3a97f58bc22498655a034e7aa7159664 Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Wed, 22 May 2024 19:24:11 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9PlatformView=E7=9B=B8?= =?UTF-8?q?=E5=85=B3md=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- ...07\346\215\242\346\214\207\345\257\274.md" | 172 ++++++++++++++++-- ...25\344\275\277\347\224\250PlatformView.md" | 134 +++++++------- 2 files changed, 223 insertions(+), 83 deletions(-) diff --git "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" index 71cb171c..6c6c751a 100644 --- "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" +++ "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" @@ -1,26 +1,170 @@ -## PlatformView同层渲染方案适配切换指导 +## PlatformView同层渲染方案适配切换指导 + +## PlatformView旧方案 +### 简述 +在Flutter适配层定义DynamicView和DVModel +```java +@Observed +export class DVModel { + id_: number; + compType: string; + params: DVModelParameters; + events: DVModelEvents; + children: DVModelChildren; + builder: Any; + public getLayoutParams(): DVModelParameters { + return this.params; + } +} +``` +```java +@Component +export struct DynamicView{ + @ObjectLink model:DVModel; + @ObjectLink children:DVModelChildren; + @ObjectLink params:DVModelParameters; + @ObjectLink events:DVModelEvents; + @BuilderParam customBuilder?:($$:BuilderParams)=>void; +} +``` +开发者使用json字符串来定义生成DVModel模型,实现PlatformView的定义,将FlutterView置于底层,DynamicView实现的PlatformView置于顶层,DynamicView使用ArkUI实现 +```java + build() { + Stack() { + XComponent({ id: this.viewId, type: this.xComponentType, libraryname: 'flutter' }) + .focusable(true) + .focusOnTouch(true) + .onLoad((context) => { + this.flutterView?.onSurfaceCreated() + Log.d(TAG, "XComponent onLoad "); + }) + .onDestroy(() => { + Log.d(TAG, "XComponent onDestroy "); + this.flutterView?.onSurfaceDestroyed() + }) + .backgroundColor(Color.Transparent) -## PlatformView旧方案 + ForEach(this.rootDvModel!!, (child: Any) => { + DynamicView({ + model: child as DVModel, + params: child.params, + events: child.events, + children: child.children, + customBuilder: child.builder + }) + }) + } +``` +所以是通过鸿蒙的原生渲染的。Flutter页面嵌入PlatformView时会有下面两个严重缺陷: + 1. PlatformView覆盖在FlutterView上面出现遮挡问题 + 2. 页面切换时,FlutterView和PlatformView动画不一致 + + + +## PlatformView新方案 ### 简述 -在Flutter适配层定义DynamicView和DVModel,通过PlatformViewChannel通道获取到的参数生成对应DVModel,并基于该DVModel和DynamicView渲染应用OHOS侧定义的OHOS原生组件 -FlutterPage中,对接Xcomponent的FlutterView置于底层,而DynamicView实现的PlatformView置于上层 +采用NodeContainer同层渲染功能,将原生平台组件的纹理导出注册到Flutter Engine,由Flutter统一渲染。可以解决旧方案的固有缺陷,并且PlatformView使用自定义ArkUI的Component组件,符合鸿蒙原生应用开发习惯,不用按照DVModel来定义,同时避免写json没有代码提示的困扰。 +```java + build() { + Stack() { + NodeContainer(this.nodeController) + .width(this.storageLinkWidth) + .height(this.storageLinkHeight) -### 缺陷 -1. PlatformView覆盖在FlutterView上面出现遮挡问题 -2. FlutterView和PlatformView动画不一致 + Text('') + .id('emptyFocusText' + this.viewId) + .size({width: 0, height: 0}) + .opacity(0) + .focusable(true) + XComponent({ id: this.viewId, type: this.xComponentType, libraryname: 'flutter' }) + .focusable(true) + .focusOnTouch(true) + .onLoad((context) => { + this.flutterView?.onSurfaceCreated() + Log.d(TAG, "XComponent onLoad "); + }) + .onDestroy(() => { + Log.d(TAG, "XComponent onDestroy "); + this.flutterView?.onSurfaceDestroyed() + }) + .backgroundColor(Color.Transparent) + } + } +``` +### 新旧方案实现关键区别: +旧方案: +DVModel: +```java +private model: DVModel = createDVModelFromJson( + { + compType: "Column", + attributes: { height: '200%'}, + children: [ + { + compType: "Text", + attributes: { value: "Native:发送数据给Dart111111111111111", fontColor: Color.Orange,backgroundColor: Color.Black,height: 100}, + events: { onClick: this.sendMessage }, + }, + { + compType: "Text", + attributes: { value: "Native:来自Dart的数据", marginTop: 20 }, + } + ], + } +); +``` +getView: +```java +getView(): DVModel { + return this.model; +} +``` +新方案: +Component: +```java +@Component +struct ButtonComponent { + @Prop params: Params + customView: CustomView = this.params.platformView as CustomView + @StorageLink('numValue') storageLink: string = "first" + @State bkColor: Color = Color.Red -## PlatformView新方案 - -### 简述 -采用NodeContainer同层渲染功能,将原生平台组件的纹理导出注册到Flutter Engine,由Flutter统一渲染 + build() { + Column() { + Button("发送数据给Flutter") + .border({ width: 2, color: Color.Blue}) + .backgroundColor(this.bkColor) + .onTouch((event: TouchEvent) => { + console.log("nodeController button on touched") + }) + .onClick((event: ClickEvent) => { + this.customView.sendMessage(); + console.log("nodeController button on click") + }) -### 区别 -1. 新方案由Flutter统一渲染,不会出现PlatformView和FlutterView不一致、相互影响的问题 -2. 由json定义改为更形象的Component组件定义;开发者可通过OHOS侧使用Component组件方式自定义页面样式组件,方便易懂,符合OHOS原生应用开发习惯 \ No newline at end of file + Text(`来自Flutter的数据 : ${this.storageLink}`) + .onTouch((event: TouchEvent) => { + console.log("nodeController text on touched") + }) + + }.alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .direction(Direction.Ltr) + .width('100%') + .height('100%') + } +} +``` +getView: +```java +getView(): WrappedBuilder<[Params]> { + return new WrappedBuilder(ButtonBuilder); +} +``` \ No newline at end of file diff --git "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" index 791f2311..a25f6ca3 100644 --- "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" +++ "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" @@ -20,54 +20,53 @@ 2. 在`platform_view_example\ohos\entry\src\main\ets\entryability`目录下实现代码 -3. 新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 - 3.1 定义一个`Component`,用于生成OHOS侧`PlatformView` +3. 新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 + 3.1 定义一个`Component`,代表ohos的`PlatformView`的定义 ```java +@Component struct ButtonComponent { - @Prop params: Params - customView: CustomView = this.params.platformView as CustomView - @StorageLink('numValue') storageLink: string = "first" - @State bkColor: Color = Color.Red - - build() { - Column() { - Button("发送数据给Flutter") - .border({ width: 2, color: Color.Blue}) - .backgroundColor(this.bkColor) - .onTouch((event: TouchEvent) => { - console.log("nodeController button on touched") - }) - .onClick((event: ClickEvent) => { - this.customView.sendMessage(); - console.log("nodeController button on click") - }) - - Text(`来自Flutter的数据 : ${this.storageLink}`) - .onTouch((event: TouchEvent) => { - console.log("nodeController text on touched") - }) - - - }.alignItems(HorizontalAlign.Center) - .justifyContent(FlexAlign.Center) - .direction(Direction.Ltr) - .width('100%') - .height('100%') - } + @Prop params: Params + customView: CustomView = this.params.platformView as CustomView + @StorageLink('numValue') storageLink: string = "first" + @State bkColor: Color = Color.Red + + build() { + Column() { + Button("发送数据给Flutter") + .border({ width: 2, color: Color.Blue}) + .backgroundColor(this.bkColor) + .onTouch((event: TouchEvent) => { + console.log("nodeController button on touched") + }) + .onClick((event: ClickEvent) => { + this.customView.sendMessage(); + console.log("nodeController button on click") + }) + + Text(`来自Flutter的数据 : ${this.storageLink}`) + .onTouch((event: TouchEvent) => { + console.log("nodeController text on touched") + }) + + }.alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .direction(Direction.Ltr) + .width('100%') + .height('100%') + } } ``` - 3.2 定义一个方法,调用自定义Component获取原生平台组件的纹理,然后通过WrappedBuilder返回出去 + 3.2 定义一个builder方法,放入3.1的自定义Component组件 ```java @Builder function ButtonBuilder(params: Params) { - ButtonComponent({ params: params }) - .backgroundColor(Color.Yellow) - // .width('50%').height('50%') + ButtonComponent({ params: params }) + .backgroundColor(Color.Yellow) } ``` - 3.3 在Customview类里面设置具体通道及方法,同时返回`WrappedBuilder`导出原生平台组件的纹理到`engine` + 3.3 继承PlatformView实现一个自定义的Customview,实现getView接口,返回`WrappedBuilder(ButtonBuilder)`,放入3.2的builder方法 ```java import MethodChannel, { MethodCallHandler, @@ -79,9 +78,6 @@ import { BinaryMessenger } from '@ohos/flutter_ohos/src/main/ets/plugin/common/B import StandardMethodCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMethodCodec'; import MethodCall from '@ohos/flutter_ohos/src/main/ets/plugin/common/MethodCall'; -import { DVModel } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicView'; -import { createDVModelFromJson } from '@ohos/flutter_ohos/src/main/ets/view/DynamicView/dynamicViewJson'; - @Observed export class CustomView extends PlatformView implements MethodCallHandler { numValue: string = "test"; @@ -92,7 +88,7 @@ export class CustomView extends PlatformView implements MethodCallHandler { constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) { super(); console.log("nodeController viewId:" + viewId) - // 注册消息通道 + // 注册消息通道,消息通道根据具体需求添加,代码仅作为示例 this.methodChannel = new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE); this.methodChannel.setMethodCallHandler(this); } @@ -127,29 +123,7 @@ export class CustomView extends PlatformView implements MethodCallHandler { } ``` -4,新建`CustomPlugin.ets`文件,用于向Flutter层注册插件 - -```java -import { FlutterPlugin, - FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; -import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; -import { CustomFactory } from './CustomFactory'; - -export class CustomPlugin implements FlutterPlugin { - getUniqueClassName(): string { - return 'CustomPlugin'; - } - - onAttachedToEngine(binding: FlutterPluginBinding): void { - binding.getPlatformViewRegistry()?. - registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); - } - - onDetachedFromEngine(binding: FlutterPluginBinding): void {} -} -``` - -5,新建`CustomFactory.ets`文件,`CustomView`工厂类需要在`CustomPlugin`里注册 +4. 实现一个自定义的`PlatformViewFactory`,在其`create`方法中创建自定义的`PlatformView`的实例 ```java import common from '@ohos.app.ability.common'; @@ -173,7 +147,29 @@ export class CustomFactory extends PlatformViewFactory { } ``` -6,打开`EntryAbility.ets`文件,添加Plugin +5. 实现一个`FlutterPlugin`插件,在`onAttachedToEngine`中,注册自定义的`PlatformViewFactory` + +```java +import { FlutterPlugin, + FlutterPluginBinding } from '@ohos/flutter_ohos/src/main/ets/embedding/engine/plugins/FlutterPlugin'; +import StandardMessageCodec from '@ohos/flutter_ohos/src/main/ets/plugin/common/StandardMessageCodec'; +import { CustomFactory } from './CustomFactory'; + +export class CustomPlugin implements FlutterPlugin { + getUniqueClassName(): string { + return 'CustomPlugin'; + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + binding.getPlatformViewRegistry()?. + registerViewFactory('com.rex.custom.ohos/customView', new CustomFactory(binding.getBinaryMessenger(), StandardMessageCodec.INSTANCE)); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void {} +} +``` + +6. 打开`EntryAbility.ets`文件,添加Plugin ```java import { FlutterAbility } from '@ohos/flutter_ohos' @@ -198,7 +194,7 @@ export default class EntryAbility extends FlutterAbility { 2,在`platform_view_example\lib`目录下实现代码 -3,新建CustomPage,用于显示Native侧的CustomView的Widget +3,新建`CustomPage`,用于显示`Native`侧的`CustomView的Widget` ```dart void main() { @@ -226,7 +222,7 @@ class CustomPage extends StatefulWidget { } ``` -4,实现_CustomPageState +4,实现`_CustomPageState` ```dart class _CustomPageState extends State { @@ -309,7 +305,7 @@ OhosView组件就是桥接Native view的关键。 - onPlatformViewCreated:PlatformView创建成功时的回调。 - creationParams:传递给NativeView的初始化参数。 -5、实现CustomOhosView,自定义OhosView,用于dart与platform之间的通道实现 +5、实现`CustomOhosView`,使用`OhosView`组件,`viewType`需要和ets侧`FlutterPlugin`做`registerViewFactory`操作时指定的`viewType`一致,用于dart与platform之间的通道实现 ```dart class CustomOhosView extends StatefulWidget { final OnViewCreated onViewCreated; @@ -347,7 +343,7 @@ class _CustomOhosViewState extends State { } ``` -6、新建CustomViewController,用于实现Dart侧与Native侧的交互 +6、新建`CustomViewController`,用于实现Dart侧与Native侧的交互 ```dart class CustomViewController { -- Gitee From 56935c803a7a6004cd344de509478f10cc436a2a Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Wed, 22 May 2024 19:30:11 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9PlatformView=E7=9B=B8?= =?UTF-8?q?=E5=85=B3md=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- ...210\207\346\215\242\346\214\207\345\257\274.md" | 14 +++++--------- ...275\225\344\275\277\347\224\250PlatformView.md" | 6 +++--- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" index 6c6c751a..40a3b98c 100644 --- "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" +++ "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" @@ -97,10 +97,9 @@ export struct DynamicView{ } ``` - -### 新旧方案实现关键区别: -旧方案: -DVModel: + +## 新旧方案实现关键区别: +旧方案: ```java private model: DVModel = createDVModelFromJson( { @@ -119,15 +118,13 @@ private model: DVModel = createDVModelFromJson( ], } ); -``` -getView: +``` ```java getView(): DVModel { return this.model; } ``` -新方案: -Component: +新方案: ```java @Component struct ButtonComponent { @@ -162,7 +159,6 @@ struct ButtonComponent { } } ``` -getView: ```java getView(): WrappedBuilder<[Params]> { return new WrappedBuilder(ButtonBuilder); diff --git "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" index a25f6ca3..a2a56b93 100644 --- "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" +++ "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" @@ -21,7 +21,7 @@ 2. 在`platform_view_example\ohos\entry\src\main\ets\entryability`目录下实现代码 3. 新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 - 3.1 定义一个`Component`,代表ohos的`PlatformView`的定义 + 3.1 定义一个`Component`,代表ohos的`PlatformView`的定义 ```java @Component struct ButtonComponent { @@ -56,7 +56,7 @@ struct ButtonComponent { } } ``` - + 3.2 定义一个builder方法,放入3.1的自定义Component组件 ```java @Builder @@ -65,7 +65,7 @@ function ButtonBuilder(params: Params) { .backgroundColor(Color.Yellow) } ``` - + 3.3 继承PlatformView实现一个自定义的Customview,实现getView接口,返回`WrappedBuilder(ButtonBuilder)`,放入3.2的builder方法 ```java import MethodChannel, { -- Gitee From ebbb95c432cb9a3b46102cff8c7c5495c996c32c Mon Sep 17 00:00:00 2001 From: cjand <1747143535@qq.com> Date: Wed, 22 May 2024 19:33:17 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9PlatformView=E7=9B=B8?= =?UTF-8?q?=E5=85=B3md=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- ...\215\345\210\207\346\215\242\346\214\207\345\257\274.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" index 40a3b98c..5412f225 100644 --- "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" +++ "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" @@ -30,7 +30,7 @@ export struct DynamicView{ @BuilderParam customBuilder?:($$:BuilderParams)=>void; } ``` -开发者使用json字符串来定义生成DVModel模型,实现PlatformView的定义,将FlutterView置于底层,DynamicView实现的PlatformView置于顶层,DynamicView使用ArkUI实现 +开发者使用json字符串来定义生成DVModel模型,实现PlatformView的定义,将FlutterView置于底层,DynamicView实现的PlatformView置于顶层,DynamicView使用ArkUI实现,所以是通过鸿蒙的原生渲染的。 ```java build() { Stack() { @@ -58,8 +58,8 @@ export struct DynamicView{ }) } ``` -所以是通过鸿蒙的原生渲染的。Flutter页面嵌入PlatformView时会有下面两个严重缺陷: - 1. PlatformView覆盖在FlutterView上面出现遮挡问题 +Flutter页面嵌入PlatformView时会有下面两个严重缺陷: + 1. PlatformView覆盖在FlutterView上面出现遮挡问题 2. 页面切换时,FlutterView和PlatformView动画不一致 -- Gitee From 5aadae27be32aa85f3c90d27bdd16f27f4413352 Mon Sep 17 00:00:00 2001 From: laoguanyao <806103474@qq.com> Date: Wed, 22 May 2024 19:55:15 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E6=94=B9PlatformView=E7=9B=B8?= =?UTF-8?q?=E5=85=B3md=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cjand <1747143535@qq.com> --- ...45\210\207\346\215\242\346\214\207\345\257\274.md" | 10 +++------- ...44\275\225\344\275\277\347\224\250PlatformView.md" | 11 ++++++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" index 5412f225..fd213521 100644 --- "a/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" +++ "b/ohos/docs/04_development/PlatformView\345\220\214\345\261\202\346\270\262\346\237\223\346\226\271\346\241\210\351\200\202\351\205\215\345\210\207\346\215\242\346\214\207\345\257\274.md" @@ -30,7 +30,7 @@ export struct DynamicView{ @BuilderParam customBuilder?:($$:BuilderParams)=>void; } ``` -开发者使用json字符串来定义生成DVModel模型,实现PlatformView的定义,将FlutterView置于底层,DynamicView实现的PlatformView置于顶层,DynamicView使用ArkUI实现,所以是通过鸿蒙的原生渲染的。 +开发者使用json字符串来定义生成DVModel模型,实现PlatformView的定义,将FlutterView置于底层,DynamicView实现的PlatformView置于顶层,DynamicView使用ArkUI实现,所以是通过鸿蒙的原生渲染的。 ```java build() { Stack() { @@ -75,12 +75,6 @@ Flutter页面嵌入PlatformView时会有下面两个严重缺陷: .width(this.storageLinkWidth) .height(this.storageLinkHeight) - Text('') - .id('emptyFocusText' + this.viewId) - .size({width: 0, height: 0}) - .opacity(0) - .focusable(true) - XComponent({ id: this.viewId, type: this.xComponentType, libraryname: 'flutter' }) .focusable(true) .focusOnTouch(true) @@ -120,6 +114,7 @@ private model: DVModel = createDVModelFromJson( ); ``` ```java +/// 自定义PlatformView实体类的实现的接口 getView(): DVModel { return this.model; } @@ -160,6 +155,7 @@ struct ButtonComponent { } ``` ```java +/// 自定义PlatformView实体类的实现的接口 getView(): WrappedBuilder<[Params]> { return new WrappedBuilder(ButtonBuilder); } diff --git "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" index a2a56b93..8ca2fd77 100644 --- "a/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" +++ "b/ohos/docs/04_development/\345\246\202\344\275\225\344\275\277\347\224\250PlatformView.md" @@ -21,6 +21,7 @@ 2. 在`platform_view_example\ohos\entry\src\main\ets\entryability`目录下实现代码 3. 新建`CustomView.ets`文件,`CustomView`用于在Flutter Widget里显示 + 3.1 定义一个`Component`,代表ohos的`PlatformView`的定义 ```java @Component @@ -169,7 +170,7 @@ export class CustomPlugin implements FlutterPlugin { } ``` -6. 打开`EntryAbility.ets`文件,添加Plugin +6. 打开`EntryAbility.ets`文件,添加Plugin(也可以把自定义PlatformView写在一个鸿蒙插件中,在应用中沿用,就不用在此显式添加插件) ```java import { FlutterAbility } from '@ohos/flutter_ohos' @@ -299,13 +300,13 @@ class _CustomPageState extends State { } ``` -OhosView组件就是桥接Native view的关键。 +OhosView组件就是桥接PlatformView的关键。 -- viewType:传递给Native侧,告知插件需要创建那个NativeView,这个NativeView需要在插件初始化时注册。 +- viewType:传递给Native侧,告知插件需要创建那个PlatformView,这个PlatformView需要在插件初始化时注册。 - onPlatformViewCreated:PlatformView创建成功时的回调。 -- creationParams:传递给NativeView的初始化参数。 +- creationParams:传递给PlatformView的初始化参数。 -5、实现`CustomOhosView`,使用`OhosView`组件,`viewType`需要和ets侧`FlutterPlugin`做`registerViewFactory`操作时指定的`viewType`一致,用于dart与platform之间的通道实现 +5、实现`CustomOhosView`,使用`OhosView`组件,`viewType`需要和ets侧`FlutterPlugin`做`registerViewFactory`操作时指定的`viewType`一致 ```dart class CustomOhosView extends StatefulWidget { final OnViewCreated onViewCreated; -- Gitee