Fluttify一周一插件 之 高德地图 Flutter插件

Logo

高德地图 地图组件 Flutter插件

GitHub地址:github.com/fluttify-pr…html

demo apk下载android

依赖

dependencies:
  flutter:
    sdk: flutter
  amap_map_fluttify: ^x.x.x
复制代码

配置

Android

  1. 注意在app/build.gradleandroid块中配置签名信息, 并在buildTypes块中指定签名信息, 不然将没法匹配到你在高德后台配置的appkey, 例如:
android {
    signingConfigs {
        release {
            keyAlias 'amap_map_test'
            keyPassword 'amap_map_test'
            storeFile file('../amap_map_test.jks')
            storePassword 'amap_map_test'
        }
    }

    buildTypes {
        debug {
            signingConfig signingConfigs.release
        }
        profile {
            signingConfig signingConfigs.release
        }
        release {
            signingConfig signingConfigs.release
        }
    }
}
复制代码

iOS

  1. 使用地图须要使能UiKitView, 在Info.plist中添加:
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
复制代码
  1. 定位须要声明权限, 在Info.plist中添加:
<key>NSLocationWhenInUseUsageDescription</key>
<string>须要定位权限</string>
复制代码
  1. 调用高德地图须要添加白名单:
<key>LSApplicationQueriesSchemes</key>
<array>
	<string>iosamap</string>
	<string>amapuri</string>
</array>
复制代码

导入

import 'package:amap_map_fluttify/amap_map_fluttify.dart';
复制代码

使用

显示地图

设置高德Key

在application标签中加入以下内容:ios

<meta-data android:name="com.amap.api.v2.apikey" android:value="key">
//开发者申请的key 
</meta-data>
复制代码

点我获取Key
点我查看Key注册时必要数据SHA1和包名的获取方法git

初始化地图容器

AmapView是 Widget 类的一个子类, 用于在 Widget树 中放置地图。 AmapView 是地图容器。用 AmapView 加载地图的方法与 提供的其余 Widget 同样,具体的使用步骤以下:github

import 'package:amap_map_fluttify/amap_map_fluttify.dart';
import 'package:flutter/material.dart';

class CreateMapScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('自定义地图')),
      body: AmapView(),
    );
  }
}
复制代码

插件已经在app生命周期回调中处理了相关回调。redis

显示地图

AmapController 类是地图的控制器类,用来操做地图。它所承载的工做包括:地图图层切换(如卫星图、黑夜地图)、改变地图状态(地图旋转角度、俯仰角、中心点坐标和缩放级别)、添加点标记(Marker)、绘制几何图形(Polyline、Polygon、Circle)、各种事件监听(点击、手势等)等,AmapController 是地图 SDK 最重要的核心类,诸多操做都依赖它完成。api

AmapView 对象初始化完毕以后,构造 AmapController 对象。示例代码以下:数组

import 'package:amap_map_fluttify/amap_map_fluttify.dart';
import 'package:flutter/material.dart';

class CreateMapScreen extends StatefulWidget {
  @override
  _CreateMapScreenState createState() => _CreateMapScreenState();
}

class _CreateMapScreenState extends State<CreateMapScreen> {
  AmapController _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('自定义地图')),
      body: AmapView(
        onMapCreated: (controller) async {
          _controller = controller;
        },
      ),
    );
  }
}
复制代码

运行您刚完成的工程就能够在您的 APP 中看到高德地图了。运行后的效果以下图所示(左Android,右iOS): 显示地图_Android 显示地图_iOSmarkdown

显示定位蓝点

定位蓝点指的是进入地图后显示当前位置点的功能。自Android 3D地图 SDK 5.0.0版本以后定位蓝点实现无需依赖 Android 定位 SDK ,5.0.0 版本以前须要引入地图 SDK 和定位 SDK 到工程中。效果以下: 定位蓝点网络

构造定位参数

final option = MyLocationOption(
  show: true, // 是否显示
  myLocationType: MyLocationType.Locate, //定位模式
  interval: Duration.zero, // 定位间隔
  strokeColor: Colors.transparent, // 精度圈边框颜色
  strokeWidth: 0, //精度圈边框宽度
  fillColor: Colors.transparent, // 精度圈填充色
  iconProvider: AssetImage('图片路径'), // 自定义定位图标
  anchorU: 0.0, // 锚点u
  anchorV: 0.0, // 锚点v
);
复制代码

定位蓝点展示模式

enum MyLocationType {
  /// 只定位
  Show,
  /// 定位一次, 并移动到中心
  Locate,
  /// 跟随
  Follow,
  /// 方向跟随
  Rotate,
}
复制代码

获取经纬度信息

经过

class AmapController {
  Future<LatLng> getLocation({
    Duration interval = const Duration(milliseconds: 500),
    Duration timeout = const Duration(seconds: 10),
  });
}
复制代码

方法获取经纬度信息,建议拿到位置以后调用逆地理编码接口获取。

显示室内地图

Android 3D地图 SDK 集成了室内地图功能,支持室内外地图一体化展现。

功能介绍

开启室内地图后,若是可见区域内包含室内地图覆盖区域(如:凯德Mall等知名商场),且缩放达到必定级别,即可直接在地图上看到精细室内地图效果。
缩放级别≥17级时,地图上能够显示室内地图。
缩放级别≥18级时,不只能够看到室内地图效果,还容许操做切换楼层,显示精细化室内地图。
以下图示:
室内地图1 室内地图2

开启室内地图方法

3D 地图 SDK中默认会关闭室内地图显示,若有须要可以使用类AmapController中的 showIndoorMap(bool enable) 自行开启。

await controller.showIndoorMap(bool enable); //true:显示室内地图;false:不显示;
复制代码

切换地图图层

地图插件提供了几种预置的地图图层,包括卫星图、白昼地图(即最多见的黄白色地图)、夜景地图、导航地图、路况图层。
插件提供图层类型枚举,详细以下: 注意:路况图层是经过开关控制,不经过常量控制。

名称 说明
MapType.Standard 标准视图
MapType.Satellite 卫星视图
MapType.Night 黑夜视图
MapType.Navi 导航视图
MapType.Bus 公交视图

卫星地图

卫星地图在显示卫片(卫星照片)的同时也能够显示路网信息,设置卫星地图的代码及显示效果以下:

await controller.setMapType(MapType.Satellite);
复制代码

显示效果以下:
satellite android satellite ios

夜景地图

设置夜景地图的代码以下:

await controller.setMapType(MapType.Night);
复制代码

显示效果以下:
night android night ios

路况图层

路况图依据实时路况数据渲染,与前两种设置方式不太相同,路况图实现的方法以下:

await controller.showTraffic(true);
复制代码

显示效果以下:
showTraffic android showTraffic ios

使用离线地图

高德3D 地图 SDK支持离线地图功能。(2D 地图 SDK 不支持离线地图功能)
离线地图可知足在无网络环境下查看地图信息的需求,在设备本地有离线地图数据的状况下,SDK 会优先加载离线地图。

离线地图UI组件

离线地图UI组件涵盖城市下载、暂停、更新、删除以及关键字城市查询等功能,是高德地图客户端离线地图功能的一个子集,UI交互风格上靠拢高德地图app,也考虑到与开发者应用UI的融合问题,尽量的保持了简约极致。如下方法实现一键完成离线地图开发:

import 'package:amap_map_fluttify/amap_map_fluttify.dart';
import 'package:flutter/material.dart';

class OfflineManagerScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('打开离线地图管理')),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // 打开离线地图UI组件
            AmapService.instance.openOfflineMapManager();
          },
          child: Text('离线地图管理'),
        ),
      ),
    );
  }
}
复制代码

UI示意:
offline android offline ios

显示英文地图

地图支持切换中英文显示。具体实现代码:

await controller.setMapLanguage(Language.English);
复制代码

显示效果以下:
english android english ios

自定义地图

高德地图支持使用可视化自定义地图模版改变底图颜色和样式,实现可视化的编辑和控制显示地图元素。

建立地图样式

高德地图开放平台的开发者在取得开发者帐号后,能够进入开发者控制台,在地图自定义平台选择“建立地图样式”,能够选择一个模板进行建立。
图片

编辑地图样式

在建立的页面的左侧列表选择任一要素编辑样式属性;也能够单击地图,在弹出的列表中选择要素进行编辑。 图片

发布地图样式并下载

编辑完成后点击右上角“保存”->“发布”,发布完成后,选择“使用方法”,而后选择“android”平台,点击“下载离线文件”。 图片 图片

设定样式文件

1、设定离线样式文件
一、在官网控制台-个人地图样式中选择与当前使用的地图SDK版本号所对应的版本进行样式文件下载:
图片

2.下载获得的Zip文件,内部目录结构以下,每一个文件都会对应 setCustomMapStyle 中一个参数:

文件名称 文件内容说明 对应参数
style_extra.data 扩展内容,如网格背景色等 styleExtraPath
style.data 具体样式配置 styleDataPath
textures.zip 纹理图片(zip文件) texturePath
import 'package:amap_map_fluttify/amap_map_fluttify.dart';
import 'package:flutter/material.dart';

class CreateMapScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: AmapView(
        zoomLevel: 10,
        onMapCreated: (controller) async {
          // styleDataPath等参数路径与使用Image.asset('path')时同理;
          await controller.setCustomMapStyle(styleDataPath: 'raw/style.data', styleExtraPath: 'raw/style_extra.data');
        },
      ),
    );
  }
}
复制代码

显示效果以下:
custom android custom ios

控件交互

控件是指浮在地图图面上的一系列用于操做地图的组件,例如缩放按钮、指南针、定位按钮、比例尺等。

缩放按钮

缩放按钮是提供给 App 端用户控制地图缩放级别的交换按钮,每次点击改变1个级别,此控件默认打开,能够经过如下方法控制其隐藏:
图片

await controller.showZoomControl(true);
复制代码

指南针

指南针用于向 App 端用户展现地图方向,默认不显示。经过以下接口控制其显示:
图片

await controller.showCompass(true);
复制代码

定位按钮

App 端用户能够经过点击定位按钮在地图上标注一个蓝色定位点,表明其当前位置。不一样于以上控件,定位按钮内部的逻辑实现依赖定位 SDK。
SDK 没有提供自定义定位按钮的功能,若是您想要实现该功能,能够浏览参考自定义定位按钮的内容。
图片

await controller.showLocateControl(true);
复制代码

比例尺控件

比例尺控件(最大比例是1:10m,最小比例是1:1000Km),位于地图右下角,可控制其显示与隐藏,设置的方法是:
图片

await controller.showScaleControl(true);
复制代码

手势交互

地图 SDK 提供了多种手势供 App 端用户与地图之间进行交互,如缩放、旋转、滑动、倾斜。这些手势默认开启,若是想要关闭某些手势,能够经过 AmapController 类提供的接口来控制手势的开关。

手势方法说明

如下是控制手势生效与否的方法:

名称 调用方法
缩放手势 AmapController.setZoomGesturesEnabled(bool)
滑动手势 AmapController.setScrollGesturesEnabled(bool)
旋转手势 AmapController.setRotateGesturesEnabled(bool)
倾斜手势 AmapController.setTiltGesturesEnabled(bool)
全部手势 AmapController.setAllGesturesEnabled(bool)

缩放手势

缩放手势可改变地图的缩放级别,地图响应的手势以下:

  • 双击地图可使缩放级别增长1 (放大)
  • 两个手指捏/拉伸

也能够禁用或启用缩放手势。禁用缩放手势不会影响用户使用地图上的缩放控制按钮。如下是控制缩放手势开启关闭的代码:

await controller.setZoomGesturesEnabled(true);
复制代码

滑动手势

您能够用手指拖动地图四处滚动(平移)或用手指滑动地图(动画效果),也能够禁用或开启平移(滑动)手势。
如下介绍控制缩放手势开启关闭的方法,示例代码以下:

await controller.isScrollGesturesEnabled(true);
复制代码

旋转手势

您能够用两个手指在地图上转动,能够旋转3D矢量地图,也能够禁用旋转手势。
如下介绍控制旋转手势开启关闭的方法,示例代码以下:

await controller.setRotateGesturesEnabled(true);
复制代码

倾斜手势

用户能够在地图上放置两个手指,移动它们一块儿向下或向上去增长或减少倾斜角,也能够禁用倾斜手势。
如下是控制倾斜手势开启关闭的代码:

await controller.setTiltGesturesEnabled(true);
复制代码

开启以中心点进行手势操做的方法:

await controller.setZoomByCenter(true);
复制代码

调用方法交互

方法交互的概念是从程序角度出发提出的。地图 SDK 提供了不少与地图交互的接口方法,例如:改变地图显示的区域(即改变地图中心点)、改变地图的缩放级别、限制地图的显示范围等。
地图视角交互的核心方法均依赖 AmapController 类提供的方法。

改变地图的中心点

若是想改变地图中心点,能够经过以下方法,animated参数能够控制是否以动画方式移动地图:

await controller.setCenterCoordinate(LatLng(23.16, 113.23), animated: false);
复制代码

改变地图的缩放级别

若是想改变地图的缩放级别,能够经过以下方法,animated参数能够控制是否以动画方式移动地图:

await controller.setZoomLevel(10, animated: false);
复制代码

限制地图的显示范围

手机屏幕仅显示设定的地图范围,例如:但愿设置仅显示北京市区地图,可以使用此功能。注意:若是限制了地图显示范围,地图旋转手势将会失效。

final southWest = LatLng(40, 116);
final northEast = LatLng(42, 118);
await controller.setMapRegionLimits(southWest, northEast);
复制代码

地图截屏功能

地图 SDK 支持对当前屏幕显示区域进行截屏,能够对地图、覆盖物(包含信息窗口)、Logo进行截取屏幕,这其中不包括地图控件、Toast窗口。
详细示例以下:

final Uint8List data = await controller.screenShot();
复制代码

返回对象为图片数据,使用Image.memory(:Uint8List)能够直接显示。

绘制点标记

点标记用来在地图上标记任何位置,例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。
地图 SDK 提供的点标记功能包含两大部分,一部分是点(俗称 Marker)、另外一部分是浮于点上方的信息窗体(俗称 InfoWindow)。同时,SDK 对 Marker 和 InfoWindow 封装了大量的触发事件,例如点击事件、长按事件、拖拽事件。
Marker 有默认风格,同时也支持自定义。因为内容丰富,如下只能展现一些基础功能的使用,详细内容可分别参考手册。
Marker
MarkerOption

绘制默认 Marker

绘制 Marker 的代码以下:

LatLng latLng = LatLng(39.906901,116.397972);
final Marker marker = controller.addMarker(MarkerOption(coordinate: latLng));
复制代码

以上代码绘制的 Marker 效果以下图:
english android english ios

Marker 经常使用属性

名称 说明
position 在地图上标记位置的经纬度值。必填参数
title 点标记的标题
snippet 点标记的内容
draggable 点标记是否可拖拽
visible 点标记是否可见
anchorU,anchorV 点标记的锚点
alpha 点的透明度

绘制自定义 Marker

可根据实际的业务需求,在地图指定的位置上添加自定义的 Marker。MarkerOptions 是设置 Marker 参数变量的类,自定义 Marker 时会常常用到。
下面以自定义 Marker 图标为例进行代码说明:

final marker = await controller.addMarker(
  MarkerOption(
    coordinate: LatLng(39.906901,116.397972),
    iconProvider: AssetImage('images/test_icon.png'),
  ),
);
复制代码

以上代码绘制的 Marker 效果以下图:
english android english ios

绘制动画效果 Marker

插件 提供了给 Marker 设置动画的方法,具体实现方法以下:

final marker = await controller.addMarker(
  MarkerOption(
    coordinate: getNextLatLng(),
    iconProvider: AssetImage('images/test_icon.png'),
    anchorU: 0.5,
    anchorV: 1,
    visible: false,
  ),
);
await marker.startAnimation(ScaleMarkerAnimation(
  fromValue: 0.8,
  toValue: 1.2,
  duration: Duration(milliseconds: 1000),
  repeatCount: 0,
));
await marker.setVisible(true);
复制代码

因为动画显示过程是异步的,若是直接添加marker并立刻执行动画的话,可能会出现marker先被添加到地图上,而后一闪而过开始执行动画。这里提供的是一个变通方法,能够先添加一个隐藏的marker,等动画开始调用以后,再显示marker。 english android english ios

可触发的 Marker 事件

Marker 点击事件

点击 Marker 时会回调AmapController::setMarkerClickedListener,监听器的实现示例以下:

await controller.setMarkerClickedListener((marker) async {
  // 点击marker后替换图片
  marker.setIcon(
    AssetImage('images/test_icon.png'),
    createLocalImageConfiguration(context),
  );
});
复制代码

Marker 拖拽事件 拖拽 Marker 时会回调AmapController::setMarkerDragListener(:onMarkerDragStart:onMarkerDragging:onMarkerDragEnd),监听器的实现示例以下:

await controller.setMarkerDragListener(
  onMarkerDragStart: (marker) async {
    // 拖拽开始
  },
  onMarkerDragging: (marker) async {
    // 拖拽中
  },
  onMarkerDragEnd: (marker) async {
    // 拖拽结束
  },
);
复制代码

绘制 InfoWindow

InfoWindow 是点标记的一部分,默认的 Infowindow 只显示 Marker 对象的两个属性,一个是 title 和另外一个 snippet,若是但愿对InfoWindow 的样式或者内容有自定义需求,能够参考以下内容。

绘制默认 Infowindow

SDK 为用户提供了默认的 InfoWindow 样式,调用 Marker 类的 showInfoWindow()hideInfoWindow() 方法能够控制显示和隐藏。当改变 Markertitlesnippet 属性时,再次调用 showInfoWindow(),能够更新 InfoWindow 显示内容。效果以下:
english android english ios

绘制自定义 InfoWindow

自定义InfoWindow须要在AmapController上调用showCustomInfoWindow,须要传入Marker对象和自定义InfoWindow的widget。注意这里的widget仅做为截图提供给原生端显示,若是widget中有按钮之类的动态内容,则转成静态截图后都是无效的。实现示例以下:

await controller.setMarkerClickedListener((marker) async {
  await controller.showCustomInfoWindow(
    marker,
    Card(
      elevation: 10,
      child: Container(
        padding: EdgeInsets.all(16),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.location_on),
            Text(await marker.title),
          ],
        ),
      ),
    ),
  );
});
复制代码

english android english ios

可触发的 InfoWindow 事件

点击 InfoWindow 时会回调AmapController.setInfoWindowClickListener(:onInfoWindowClicked),监听器的实现示例以下:

await controller.setInfoWindowClickListener((marker) async {
  toast('${await marker.title}, ${await marker.coordinate}');
});
复制代码

绘制折线

地图上绘制的线是由 Polyline 类定义实现的,线由一组经纬度(LatLng对象)点链接而成。

绘制一条线

与点标记同样,Polyline 的属性操做集中在 PolylineOption 类中,添加一条线的示例以下:

await controller.addPolyline(PolylineOption(
  coordinateList: [
    LatLng(39.999391, 116.135972),
    LatLng(39.898323, 116.057694),
    LatLng(39.900430, 116.265061),
    LatLng(39.955192, 116.140092),
  ],
  strokeColor: Colors.red,
  width: 10,
));
复制代码

上面的代码定义该折线的颜色为红色,宽度为 10 像素,效果以下图:
english android english ios

绘制线经常使用参数

名称 说明
coordinateList 折线经纬度列表
width 折线宽度
strokeColor 折线颜色
textureProvider 自定义纹理
lineCapType 线段末端样式
lineJoinType 线段链接处样式
dashType 是否虚线

绘制面

地图上的面分为圆形和多边形两种。

绘制圆

圆形由 Circle 类定义实现,构造一个圆形须要肯定它的圆心和半径,具体的示例代码以下:

await controller.addCircle(CircleOption(
  center: LatLng(39.999391, 116.135972),
  radius: 10000,
  width: 10,
  strokeColor: Colors.green,
));
复制代码

上面的代码定义该圆形的边线颜色为绿色,宽度10 像素,效果以下图:
offline android offline ios

绘制多边形

多边形是由 Polygon 类定义的一组在地图上的封闭线段组成的图形,它由一组 LatLng 点按照传入顺序链接而成的封闭图形。与绘制线相似,面的属性操做集中在 PolygonOption 中。

final polygon = await controller.addPolygon(PolygonOption(
  coordinateList: [
    LatLng(39.999391, 116.135972),
    LatLng(39.898323, 116.057694),
    LatLng(39.900430, 116.265061),
    LatLng(39.955192, 116.140092),
  ],
  width: 10,
  strokeColor: Colors.green,
));
复制代码

上面的代码定义该圆形的边线颜色为绿色,宽度10 像素,效果以下图:
offline android offline ios

绘制热力图

热力图功能提供将业务数据展现在地图上,能够给使用者直观描述一个区域的人员,车辆等事物的热度状况。

组织热力图数据

如下以本地模拟数据为例,简单说明 SDK 热力图须要的是经纬度点数组/列表数据。

示例代码以下:

await controller.addHeatmapTileOverlay(
  HeatmapTileOption(
    coordinateList: getNextBatchLatLng(50),
    gradient: RadialGradient(
      colors: [Colors.blue, Colors.yellow, Colors.red],
      stops: <double>[0.08, 0.4, 1.0],
    ),
  ),
);
复制代码

效果图以下:
offline android offline ios

点平滑移动

功能说明:根据输入的关键点和时间参数,实现点的平滑移动效果。
使用场景:可应用到展现车辆行驶轨迹、用户移动轨迹等场景。
效果示例:
english android english ios

如何实现点平滑移动

实现平滑移动的配置参数都在SmoothMoveMarkerOption类内,其中path是移动路径的经纬度列表,iconProvider为marker图片,duration为动画时长。

await controller.addSmoothMoveMarker(
  SmoothMoveMarkerOption(
    path: [for (int i = 0; i < 10; i++) getNextLatLng()],
    iconProvider: AssetImage('images/test_icon.png'),
    duration: Duration(seconds: 10),
  ),
);
复制代码

绘制海量点图层

应用于移动端的海量点图层用于批量展示具备类似属性的坐标点数据。海量点图层支持处理的点数量级跨度较大,从几十个点至十万个点(建议不超过100000个点数据)均可以应用海量点图层进行处理。

以下图所示的处理上万个点的海量点图层效果:
图

展现海量点

添加海量点与添加普通Marker相似,只须要构造对应类型参数便可。
示例代码:

final overlay = await controller.addMultiPointOverlay(
  MultiPointOption(
    pointList: [
      for (int i = 0; i < 10000; i++)
        PointOption(
          coordinate: getNextLatLng(),
          id: i.toString(),
          title: 'Point$i',
          snippet: 'Snippet$i',
          object: 'Object$i',
        )
    ],
    iconProvider: AssetImage('images/test_icon.png'),
  ),
);
复制代码

在返回的overlay对象上调用remove方法,便可删除对应海量点图层。

海量点点击事件

await controller.setMultiPointClickedListener(
  (id, title, snippet, object) async {
    toast(
      'id: $id, title: $title, snippet: $snippet, object: $object',
    );
  },
);
复制代码

LICENSE

Copyright (C) 2020 yohom

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see www.gnu.org/licenses/.

相关文章
相关标签/搜索