Flutter中的高德地图适配鸿蒙

众所周知,虽然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) {
      super(createArgsCodes)

    this.message = message;
  }

  public create(context: common.Context, viewId: number, args: Any): PlatformView {
		return new AMapView(context, viewId, args, this.message);
	}

} 
  

第三步:创建 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, 需要自己一个个去实现对接。 

你可能感兴趣的:(harmonyos,华为)