众所周知,虽然Flutter 3.22版本编译到鸿蒙,已经没什么问题了。 但是,还是特别多的好用的Flutter插件未适配鸿蒙。
比如我们已经集成好的高德地图Flutter版的SDK, 并没有适配鸿蒙。 于是,只能自己动手术了。
首先,Flutter版本的高德地图SDK如果你不想动它的话,直接去实现鸿蒙端的 Plugin 就可以了。
第一步:创建 AMapFlutterMapPlugin ,注意名字什么的,和高德官方的Flutter SDK保持一样。
import {
Any,
BasicMessageChannel, FlutterPlugin, FlutterPluginBinding,
MethodCall,
MethodChannel,
MethodResult,
StandardMessageCodec} from "@ohos/flutter_ohos";
import AMapPlatformViewFactory from "./AMapPlatformViewFactory";
export default class AMapFlutterMapPlugin implements FlutterPlugin {
onDetachedFromEngine(binding: FlutterPluginBinding): void {
this.channel?.setMethodCallHandler(null)
}
private channel?:MethodChannel;
private basicChannel?: BasicMessageChannel;
private VIEW_TYPE : string = "com.amap.flutter.map";
getUniqueClassName(): string {
return "AMapFlutterMapPlugin"
}
onAttachedToEngine(binding: FlutterPluginBinding): void {
binding.getPlatformViewRegistry().registerViewFactory(this.VIEW_TYPE, new AMapPlatformViewFactory(binding.getBinaryMessenger(),StandardMessageCodec.INSTANCE))
}
}
第二步:创建 AMapPlatformViewFactory , 因为高德的地图只能是原生View显示,所以需要这个东西,把它显示到Flutter端。 这就需要这个工厂来支持一下
import { Any, BinaryMessenger, MessageCodec, PlatformView, PlatformViewFactory } from "@ohos/flutter_ohos";
import { common } from "@kit.AbilityKit";
import { AMapView } from "./AMapView";
export default class AMapPlatformViewFactory extends PlatformViewFactory {
message: BinaryMessenger;
constructor(message: BinaryMessenger, createArgsCodes: MessageCodec
第三步:创建 AMapView, 这个主要是在Flutter端来对接原生端的 View的,通过 PlatformView 就可以把鸿蒙原生的View显示到Flutter端。
import { BinaryMessenger, MethodCall, MethodCallHandler, MethodChannel,
MethodResult,
StandardMethodCodec } from "@ohos/flutter_ohos";
import PlatformView, { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'
import { common } from "@kit.AbilityKit";
import { AMapBuilder } from "./AMapComponent";
export class AMapView extends PlatformView implements MethodCallHandler {
methodChannel: MethodChannel;
constructor(context: common.Context, viewId: number , args: ESObject, message: BinaryMessenger) {
super();
this.methodChannel = new MethodChannel(message, `amap_flutter_map_${viewId}`, StandardMethodCodec.INSTANCE);
this.methodChannel.setMethodCallHandler(this);
}
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;
link1.set(value)
console.log("nodeController receive message from dart: ");
result.success(true);
break;
}
}
getView(): WrappedBuilder<[Params]> {
return new WrappedBuilder(AMapBuilder);
}
public sendMessage = () => {
console.log("nodeController sendMessage")
//向Dart侧发送消息
this.methodChannel.invokeMethod('getMessageFromOhosView', 'natvie - ');
}
dispose(): void {
}
}
第四步:实现地图的 Component , 这里就是具体的对接鸿蒙版高德地图的地方, 你需要把鸿蒙版的高德地图SDK导入到鸿蒙的工程,然后,在这里创建就好了,然后你需要在地图上显示按钮什么的,都可以在这里实现。
import { MapsInitializer, MapView, MapViewComponent, MapViewManager } from '@amap/amap_lbs_map3d'
import { Params } from '@ohos/flutter_ohos/src/main/ets/plugin/platform/PlatformView'
import { AMapView } from './AMapView'
const key = "e78cc8866f80adb775f9201eb99defc0";
@Component
struct AMapComponent {
@Prop params: Params
customView: AMapView = this.params.platformView as AMapView
@StorageLink('numValue') storageLink: string = "first"
@State bkColor: Color = Color.Red
aboutToAppear(): void {
MapsInitializer.setApiKey(key);
MapsInitializer.setDebugMode(true);
MapViewManager.getInstance().registerMapViewCreatedCallback((mapview?: MapView, mapViewName?: string) => {
if (!mapview) {
return;
}
let mapView = mapview;
mapView.onCreate();
mapView.getMapAsync((map) => {
})
})
}
build() {
Stack() {
MapViewComponent({ mapViewName: "harmony_map_demo" }).zIndex(0)
Column() {
}
}
.direction(Direction.Ltr)
.width('100%')
.height('100%')
}
}
@Builder
export function AMapBuilder(params: Params) {
AMapComponent({ params: params })
.backgroundColor(Color.Yellow)
}
注意,以上的代码,都是鸿蒙端写的,我是直接写在我们的项目里了, 并没有去修改高德官方的flutter工程,我太懒了,他那个代码也太旧了,懒得动它。
最后,注意在高德的Flutter 代码中,找到如下的位置 ,增加对鸿蒙PlatformView的支持。
if (defaultTargetPlatform == TargetPlatform.android) {
creationParams['debugMode'] = kDebugMode;
return AndroidView(
viewType: VIEW_TYPE,
onPlatformViewCreated: onPlatformViewCreated,
gestureRecognizers: gestureRecognizers,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
return UiKitView(
viewType: VIEW_TYPE,
onPlatformViewCreated: onPlatformViewCreated,
gestureRecognizers: gestureRecognizers,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
// else if (defaultTargetPlatform == TargetPlatform.ohos) {
// return OhosView( viewType: VIEW_TYPE,
// onPlatformViewCreated: onPlatformViewCreated,
// gestureRecognizers: gestureRecognizers,
// creationParams: creationParams,
// creationParamsCodec: const StandardMessageCodec(),
// );
// }
以上,只是实现了把地图显示出来,这样做完,我们自己工程的Flutter代码不需要修改什么,
当然,最好的办法,肯定是把高德的代码拉到私仓,然后在上面修改, 这样自己用得爽的同时,还能共享给别人使用。
如果,想进一步实现地图上的各种API, 需要自己一个个去实现对接。