HarmonyOS鸿蒙Next中flutter使用platformView怎么同时构建不同组件供flutter端使用
HarmonyOS鸿蒙Next中flutter使用platformView怎么同时构建不同组件供flutter端使用 f目前在学习flutter混合鸿蒙的方法中,想要在尝试在flutter混合鸿蒙组件的场景,官方提供的方案是单个组件混合,多个组件分场景调用的话需要怎么实现呢
这个是官方代码的示例
更多关于HarmonyOS鸿蒙Next中flutter使用platformView怎么同时构建不同组件供flutter端使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
尊敬的开发者,您好,
请问您是需要在flutter中根据不同的场景切换platformView显示的组件吗?还请看下通过if语句切换显示的组件的方式是否满足您的需求呢:
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 { webview } from '@kit.ArkWeb';
import {
photoAccessHelper,
RecentPhotoOptions,
PhotoSource,
RecentPhotoCheckResultCallback,
RecentPhotoClickCallback,
BaseItemInfo
} from '@kit.MediaLibraryKit';
import { RecentPhotoCheckInfoCallback, RecentPhotoInfo } from '@ohos.file.RecentPhotoComponent';
@Component
struct ButtonComponent {
@ObjectLink params: Params
customView: CustomView = this.params.platformView as CustomView
@StorageLink('numValue') storageLink: string = "first"
@StorageLink('viewCase') viewCase: number = 1;
@State bkColor: Color = Color.Red
private webviewController: webview.WebviewController = new webview.WebviewController();
private recentPhotoOptions: RecentPhotoOptions = new RecentPhotoOptions();
private recentPhotoCheckResultCallback: RecentPhotoCheckResultCallback =
(recentPhotoExists: boolean) => this.onRecentPhotoCheckResult(recentPhotoExists);
private recentPhotoClickCallback: RecentPhotoClickCallback =
(recentPhotoInfo: BaseItemInfo): boolean => this.onRecentPhotoClick(recentPhotoInfo);
private recentPhotoCheckInfoCallback: RecentPhotoCheckInfoCallback =
(recentPhotoExists: boolean, info: RecentPhotoInfo) => this.onRecentPhotoCheckInfo(recentPhotoExists, info);
aboutToAppear() {
this.recentPhotoOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE;
this.recentPhotoOptions.period = 30;
this.recentPhotoOptions.photoSource = PhotoSource.ALL;
}
private onRecentPhotoCheckResult(recentPhotoExists: boolean): void {
// 存在符合条件的照片或视频。
if (recentPhotoExists) {
console.info('The photo is exist.');
}
}
private onRecentPhotoClick(recentPhotoInfo: BaseItemInfo): boolean {
// 照片或视频返回。
if (recentPhotoInfo) {
console.info('The photo uri is ' + recentPhotoInfo.uri);
return true;
}
return true;
}
private onRecentPhotoCheckInfo(recentPhotoExists: boolean, info: RecentPhotoInfo): void {
// 是否存在符合条件的照片或视频,若存在则可以拿到该照片或视频的相关信息。
}
build() {
Column() {
Text('viewCase: ' + this.viewCase)
if (this.viewCase === 1) {
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")
})
}
.height('50%')
.width('50%')
.backgroundColor(Color.Pink)
} else if (this.viewCase === 2) {
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")
})
}
.height('50%')
.width('50%')
.backgroundColor(Color.Yellow)
}
}
}
}
@Builder
function ButtonBuilder(params: Params) {
ButtonComponent({ params: params })
}
AppStorage.setOrCreate('numValue', 'test')
AppStorage.setOrCreate('viewCase', 1)
@Observed
export class CustomView extends PlatformView implements MethodCallHandler {
numValue: string = "test";
viewCase: number = 1;
methodChannel: MethodChannel;
index: number = 1;
constructor(context: common.Context, viewId: number, args: ESObject, message: BinaryMessenger) {
super();
// 注册消息通道
this.methodChannel =
new MethodChannel(message, `com.rex.custom.ohos/customView${viewId}`, StandardMethodCodec.INSTANCE);
this.methodChannel.setMethodCallHandler(this);
}
onMethodCall(call: MethodCall, result: MethodResult): void {
// 接受Dart侧发来的消息
let method: string = call.method;
let link1: SubscribedAbstractProperty<number> = AppStorage.link('numValue');
let link2: SubscribedAbstractProperty<number> = AppStorage.link('viewCase');
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;
case 'changeViewCase':
let viewNumber: ESObject = call.args;
this.viewCase = viewNumber;
link2.set(viewNumber);
result.success(true);
break;
}
}
public sendMessage = () => {
console.log("nodeController sendMessage")
//向Dart侧发送消息
this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ' + this.index++);
}
getView(): WrappedBuilder<[Params]> {
return new WrappedBuilder(ButtonBuilder);
}
dispose(): void {
}
}
mian.dart:
import 'dart:math';
import 'package:flutter/material.dart';
import 'custom_ohos_view.dart';
void main() {
runApp(const MaterialApp(home: MyHome()));
}
class MyHome extends StatelessWidget {
const MyHome({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Scaffold(
body: CustomExample(),
);
}
}
class CustomExample extends StatefulWidget {
const CustomExample({Key? key}) : super(key: key);
@override
State<CustomExample> createState() => _CustomExampleState();
}
class _CustomExampleState extends State<CustomExample> {
String receivedData = '';
CustomViewController? _controller;
void _onCustomOhosViewCreated(CustomViewController controller) {
_controller = controller;
_controller?.customDataStream.listen((data) {
//接收到来自OHOS端的数据
setState(() {
receivedData = '来自ohos的数据:$data';
});
});
}
Widget _buildOhosView() {
return Expanded(
child: Container(
color: Colors.blueAccent.withAlpha(60),
child: CustomOhosView(_onCustomOhosViewCreated),
),
flex: 1,
);
}
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'),
),
TextButton(
onPressed: () {
_controller
?.changeViewCase();
},
child: const Text('切换viewCase'),
),
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,
);
}
@override
Widget build(BuildContext context) {
return Column(
children: [
_buildOhosView(),
_buildFlutterView(),
],
);
}
}
CustomOhosView.dart:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
typedef OnViewCreated = Function(CustomViewController);
///自定义OhosView
class CustomOhosView extends StatefulWidget {
final OnViewCreated onViewCreated;
const CustomOhosView(this.onViewCreated, {Key? key}) : super(key: key);
@override
State<CustomOhosView> createState() => _CustomOhosViewState();
}
class _CustomOhosViewState extends State<CustomOhosView> {
late MethodChannel _channel;
@override
Widget build(BuildContext context) {
return _getPlatformFaceView();
}
Widget _getPlatformFaceView() {
return OhosView(
viewType: 'com.rex.custom.ohos/customView',
onPlatformViewCreated: _onPlatformViewCreated,
creationParams: const <String, dynamic>{'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);
}
}
class CustomViewController {
final MethodChannel _channel;
final StreamController<String> _controller = StreamController<String>();
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<String> get customDataStream => _controller.stream;
// 发送数据给native
Future<void> sendMessageToOhosView(String message) async {
await _channel.invokeMethod(
'getMessageFromFlutterView',
message,
);
}
Future<void> changeViewCase() async {
await _channel.invokeMethod(
'changeViewCase',
2,
);
}
}
若是不满足您的场景,还请您详细描述下您的场景,是需要加载任意自定义的页面还是加载简单的组件场景。
更多关于HarmonyOS鸿蒙Next中flutter使用platformView怎么同时构建不同组件供flutter端使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
虽然也可以用这种组件的形式来加载不同页面,不过还是想知道直接加载不同的页面的话具体代码是怎么实现呢
尊敬的开发者,您好,
请问下您是需要应用在启动阶段加载不同的页面,还是希望在应用运行时通过应用内的按钮或者其他方式控制切换同层渲染的ArkTS组件?
抱歉,我前面说错了,我想实现的是可以加载不同组件的场景,但是如果组件布局比较复杂(不适合用示例中的将不同组件引入到一个组件中区分调用),这种需要区分编写的场景需要怎么处理,大概的就像二楼说的那样,但是我在实现的时候有些细节不理解,还是不知怎么实现
参考文档
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
同问
在 HarmonyOS Next 中,Flutter 使用 PlatformView 同时构建不同组件时,需在鸿蒙侧注册多个 PlatformViewFactory,每个 Factory 对应一个 unique viewType。Flutter 端通过 AndroidView(对标鸿蒙 PlatformView)并指定不同 viewType 来区分。鸿蒙侧工厂实现中,返回对应的 ArkUI 原生组件即可。


