MattTheTekie

在Flutter2.0中使用高德地图

前言

在学习过程中需要用到地图组件,但是迫于国内环境,无法使用封装好的Google地图,只能使用国内目前有的百度和高德。因为老项目用的是高德,所以这边踩高德的坑。

文档地址

官方文档

开始使用

申请Key

首先是申请高德的Key,这一步比较简单,跟着官方文档走一般没有问题。

配置SDK

因为flutter插件默认不带地图SDK,我们需要通过原生的方式来引入SDK,官方也是通过Android的文档来告诉我们怎么做的,可能有些小伙伴第一次接触有点看不懂,我这里也写一下方便自己记忆。

  • 根据文档我们跳转到这个页面。有拷贝添加Gradle继承两种方法,这边我们为了方便使用Gradle
  • 正常情况下仓库地址已经配置好了,所以配置仓库可以跳过
  • 之后在项目下的android/app/build.gradle文件中找到dependencies添加以下几行
dependencies {
    //...
    compile fileTree(dir: 'libs', include: ['*.jar'])
    //3D地图so及jar
    compile 'com.amap.api:3dmap:latest.integration'
    //定位功能
    compile 'com.amap.api:location:latest.integration'
    //...
}
  • 到这配置SDK这一步就完成了
  • 不过还是有可能会出现网络异常的情况,没找到其他解决方案,只能多试试或者代理

集成Flutter插件

  • 在flutter项目中引入amap_flutter_map: ^1.0.0(版本号可不填,默认最新)
  • 编写widget
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';

class MyMap extends StatefulWidget {
  @override
  _MyMapState createState() => _MyMapState();
}

class _MyMapState extends State<MyMap> {
  static const AMapApiKey amapApiKeys =
      AMapApiKey(androidKey: '填入你申请的key');

  AMapController _mapController;
  void onMapCreated(AMapController controller) {
    setState(() {
      _mapController = controller;
      getApprovalNumber();
    });
  }

  /// 获取审图号
  void getApprovalNumber() async {
    //普通地图审图号
    String mapContentApprovalNumber =
        await _mapController?.getMapContentApprovalNumber();
    //卫星地图审图号
    String satelliteImageApprovalNumber =
        await _mapController?.getSatelliteImageApprovalNumber();
    print("$mapContentApprovalNumber and $satelliteImageApprovalNumber");
  }

  @override
  Widget build(BuildContext context) {
    final AMapWidget map = AMapWidget(
      apiKey: amapApiKeys,
      onMapCreated: onMapCreated,
      initialCameraPosition:
          CameraPosition(target: LatLng(39.83309, 116.290176), zoom: 15),
    );
    return Container(
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
      child: map,
    );
  }
}
  • 之后调用MyMap这个widget就可以成功引入地图啦

Markers

生成点标记和印象里Web端的操作不同,这边需要提前在地图上定义好一个Marker的集合

// 提前定义
final Map<String, Marker> _initMarkerMap = <String, Marker>{};

final AMapWidget map = AMapWidget(
  apiKey: amapApiKeys,
  onMapCreated: onMapCreated,
  // 使用
  markers: Set<Marker>.of(_initMarkerMap.values),
  initialCameraPosition:
      CameraPosition(target: LatLng(28.000575, 120.672111), zoom: 15),
);

后续的增删改Marker通过setState来实现

void createMarkers(LatLng target) {
  // 创建marker时没法携带id
  // 创建后会自动携带一个随机生成的id
  final Marker marker = Marker(
      position: target);

  setState(() {
    // 通过id来判断是新marker还是旧marker
    _initMarkerMap[marker.id] = marker;
  });
}

不过大部分情况下我们需要修改marker的位置,所以我们会重新生成一个Marker,但是此时marker的id会重新生成,建议各位在初始化各个点位前,自己赋值在_initMarkerMap

void createMarkers(LatLng target) {
  final Marker marker = Marker(
      position: target);

  setState(() {
    // 自己赋值一个000的id
    // 后续修改这个marker,只需要找到000就可以了
    _initMarkerMap["000"] = marker;
  });
}

小结

  • 通过Gradle的方式来引入SDK可能会因为网络问题导致打包慢,可以耐心等等,只要没报错,应该是正常在跑的,实在觉得慢可以通过拷贝的方式。
  • 如果没引入sdk,在运行的时候项目会直接奔溃停止,之前没引入被整了半天看不懂
  • 官方的demo写得是真的乱,什么东西都往上面放