Android地图—— Mapbox 10.3.0 接入与基础使用
Android地图—— Mapbox 10.3.0 接入与基础使用
- Mapbox初始配置:依赖添加
- 1. 编辑 项目目录/build.gradle (设置maven库的访问);
- 2. 前往mapbox官网 创建账号 并 申请密钥;
- 3. 在项目中配置公钥、私钥;
- 4. 在 模块目录 /build.gradle 中添加依赖;
- 5. 配置获取用户定位权限;(可选)
- MapBox部分功能的Android实现:
- · 地图MapView的添加
- · MapBox初始化以及地图显示:
- 1. 相机设置:
- 2. 地图加载:
- · MapBox各种功能插件获取:
- 1. 地图 Logo 插件
- 2. 地图Logo旁属性按钮插件
- 3. 比例尺Scalebar插件
- 4. 指南针插件
- 5. 相机动画插件
- 6. 地图手势监听插件
- 7. 用户地理位置获取插件
- 8. 地图标记插件
Mapbox初始配置:依赖添加
官网教程指引: https://docs.mapbox.com/android/maps/guides/install/
我使用的android studio版本是旧版,依赖添加方式如下:
1. 编辑 项目目录/build.gradle (设置maven库的访问);
Android Studio less than Arctic Fox (2020.3.1) and Gradle less than v6.0:
注意,是在 allprojects 内设置!
2. 前往mapbox官网 创建账号 并 申请密钥;
Token申请地址: https://account.mapbox.com/
申请token时记得勾选 Downloads:Read 以获取从maven库下载mapbox依赖文件的许可。
创建完成之后在Token页面会有两个Token:
其中一个为初始就有的公钥;一个为你刚刚申请好的带有Downloads:Read权限的私钥。
(注意:私钥申请完成后要直接复制保存,刷新页面后会被隐藏)。
3. 在项目中配置公钥、私钥;
在 项目目录下的 gradle.properites 中添加以下代码,用于从maven库下载mapbox相关依赖的身份验证。
MAPBOX_DOWNLOADS_TOKEN=自己申请的私钥在 res/valuses/strings.xml 文件中添加以下代码。mapbox默认你 将token放置在 strings.xml 中,在调用相关api时会 自动 在此文件夹下面获取token。
<string name="mapbox_access_token">公钥</string>4. 在 模块目录 /build.gradle 中添加依赖;
// mapbox地图组件 implementation 'com.mapbox.maps:android:10.3.0'5. 配置获取用户定位权限;(可选)
在 AndroidManifest.xml 文件中添加以下代码*(当你需要在地图上显示用户位置时才需要配置)*
注意: 还需要在代码中动态请求该权限,Mapbox也提供了PermissionsManager(可参考官网示例)工具用于动态请求权限,这里不展开)
可能遇到的问题:
① sync gradle文件时报warnning:
问题: Failed to resolve: com.mapbox.maps:android:10.0.3
解决: 检查自己申请的token是否带有 Downloads:Read,在创建token时记得勾选上,系统默认提供的token是不带这个scope的,需要自行申请。
————————————————————————————————————————————
MapBox部分功能的Android实现:
这部分对MapBox的主要用例的Android实现和原理进行相关解释(示例版本10.3.0)。
由于官网有kotlin代码的例子,以下功能展示均使用 java代码 进行举例。
以下介绍的功能代码我都封装到了MapBoxUtil.java文件中,可以在这个项目里面自行获取。(结合这个示例项目的代码阅读更佳哦)
效果图先行:
· 地图MapView的添加
layout文件中添加MapView视图:
<com.mapbox.maps.MapViewandroid:id="@+id/mapview"android:layout_width="match_parent"android:layout_height="match_parent"/>Java文件:
MapView mMapView = findViewById(R.id.mapview); MapboxMap mMapboxMap = mapView.getMapboxMap();· MapBox初始化以及地图显示:
1. 相机设置:
相机部分参数初始变量定义:
private static final double DEFAULT_LOCATION_LATITUDE = 22.55; // 初始地图显示坐标(深圳) private static final double DEFAULT_LOCATION_LONGITUDE = 114.06; private static final double DEFAULT_ZOOM_VALUE = 8.0; // 初始地图缩放大小相机设置:
mMapboxMap.setCamera( // 设置地图相机初始位置new CameraOptions.Builder().center(Point.fromLngLat(DEFAULT_LOCATION_LONGITUDE, DEFAULT_LOCATION_LATITUDE)).zoom(DEFAULT_ZOOM_VALUE).build());相机更多参数设置:
https://docs.mapbox.com/android/maps/guides/camera-and-animation/camera/
2. 地图加载:
地图类型变量定义:
private static final String DEFAULT_MAP_STYLE = Style.MAPBOX_STREETS; // 地图显示样式加载地图:
mMapboxMap.loadStyleUri( // 加载地图DEFAULT_MAP_STYLE, style -> {// style 加载完成回调});更多地图类型:
https://docs.mapbox.com/android/maps/guides/styles/set-a-style/
· MapBox各种功能插件获取:
mMapView .getPlugin(Plugin.MAPBOX_XXX_PLUGIN_ID); //XXX因插件而异1. 地图 Logo 插件
LogoPlugin logoPlugin = mMapView .getPlugin(Plugin.MAPBOX_LOGO_PLUGIN_ID); // 隐藏 Logo if (logoPlugin != null) {logoPlugin.setEnabled(false); }2. 地图Logo旁属性按钮插件
AttributionPlugin attributionPlugin = mMapView .getPlugin(Plugin.MAPBOX_ATTRIBUTION_PLUGIN_ID); // 隐藏 属性按钮 if (attributionPlugin != null) {attributionPlugin.setEnabled(false); }3. 比例尺Scalebar插件
ScaleBarPlugin scaleBarPlugin = mMapView .getPlugin(Plugin.MAPBOX_SCALEBAR_PLUGIN_ID); // 隐藏 比例尺 if (scaleBarPlugin != null) {scaleBarPlugin.setEnabled(false); }4. 指南针插件
CompassPlugin compassPlugin = mMapView .getPlugin(Plugin.MAPBOX_COMPASS_PLUGIN_ID); if (compassPlugin == null) {return; } compassPlugin.setEnabled(isEnable); // 隐藏指南针 compassPlugin.setImage(drawable); // 更换指南针icon以上UI相关的插件均可以通过相关api设置显示位置和大小,这里不举例说明。
5. 相机动画插件
相机位置改变:
若只是简单的直接改变相机位置的话,使用上述相机初始化中的mMapboxMap.setCamera方法即可。
若想要添加移动的动画,如从当前显示位置缓慢变换到目的位置,则需要相机动画插件CameraAnimationsPlugin
相机移动方法举例:
/*** 将摄像头移动到指定位置* @param point 目标坐标* @param zoom 目标缩放比例* @param duration 滑动总时间 0为无动画*/ public void moveCameraTo(Point point, double zoom, int duration) {if (mMapView == null) {return;}if (duration != 0 && cameraAnimationsPlugin != null) {cameraAnimationsPlugin .flyTo(new CameraOptions.Builder().center(point).zoom(zoom).build(),new MapAnimationOptions.Builder().duration(duration).build());} else {mMapboxMap.setCamera(new CameraOptions.Builder().center(point).zoom(zoom).build());} }更多相机动画:
https://docs.mapbox.com/android/maps/guides/camera-and-animation/animations
6. 地图手势监听插件
可以监听地图相关运行中状态,Mapbox提供了手势插件供我们监听各种地图状态:
GesturesPlugin gesturesPlugin = mMapView.getPlugin(Plugin.MAPBOX_GESTURES_PLUGIN_ID);下面以监听地图移动为例:
if (gesturesPlugin != null) {gesturesPlugin .addOnMoveListener(onMoveListener); // 注意onDestroy时要remove掉Listener } // 地图移动监听 private final OnMoveListener onMoveListener = new OnMoveListener() {@Overridepublic void onMoveBegin(@NotNull MoveGestureDetector moveGestureDetector) {// 地图开始移动}@Overridepublic boolean onMove(@NotNull MoveGestureDetector moveGestureDetector) {return false;}@Overridepublic void onMoveEnd(@NotNull MoveGestureDetector moveGestureDetector) {// 地图移动结束} };更多用户交互监听:
https://docs.mapbox.com/android/maps/guides/user-interaction
7. 用户地理位置获取插件
效果图先行:
MapBox获取用户位置主要通过 LocationComponentPlugin 插件获取:
LocationComponentPlugin locationPlugin = mMapView.getPlugin(Plugin.MAPBOX_LOCATION_COMPONENT_PLUGIN_ID);① 设置用户位置点显示UI样式:
设置脉冲显示效果:
locationPlugin.updateSettings(locationComponentSettings -> {locationComponentSettings.setEnabled(true);locationComponentSettings.setPulsingEnabled(true); // 脉冲效果return null; });设置位置点样式:
通过插件的 setLocationPuck() 方法进行设置,方法接受四个参数。前三个为上\中\下层图标样式设置,最后一个接受 Expression表达式 用于配置 位置点图标的缩放scale数值规则。
(Expression表达式的本质是Json语句,是Mapbox自定义的一种描述性变量,具体Expression所涵盖的运算符可参考官网,我们可以在使用的过程中逐渐了解各运算符具体含义)
这里我们选择 生成一个随地图缩放变化规则的Expression:
我们使用 InterpolatorBuilder 来生成一个插值表达式。
下面例子的插值表达式表示当地图zoom为0时,图标scale为1;当zoom为20时,图标scale为1.5;其间值线性插值获得。
- linear运算符用于对一队stop值间的数据做线性插值运算;
- zoom表达式添加上了图标大小随地图缩放大小的羁绊。
从结果上来看即生成了如下json表达式:(清楚Expression编写规则后,直接编写json表达式也可以实现同样的效果)
["interpolate",["linear"],["zoom"],0.0,1.0,20.0,1.5]代码如下所示:
// 设置图标随地图缩放比例变化 Expression.InterpolatorBuilder interpolatorBuilder = new Expression.InterpolatorBuilder("interpolate"); interpolatorBuilder.linear(); interpolatorBuilder.zoom(); interpolatorBuilder.stop(expressionBuilder -> {expressionBuilder.literal(0.0);expressionBuilder.literal(1.0);return null; }); interpolatorBuilder.stop(expressionBuilder -> {expressionBuilder.literal(20.0);expressionBuilder.literal(1.5);return null; }); // 设置用户位置图标样式 locationPlugin.setLocationPuck(new LocationPuck2D(null,AppCompatResources.getDrawable(mContext, R.drawable.mapbox_user_icon),AppCompatResources.getDrawable(mContext, R.drawable.mapbox_user_stroke_icon),interpolatorBuilder.build().toJson()));官网例子:
https://docs.mapbox.com/help/tutorials/mapbox-gl-js-expressions/#add-a-zoom-expression
② 添加用户位置监听器
// 添加用户位置监听器 // 注意onDestroy时要remove掉Listener locationPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener); // 用户位置改变监听 private final OnIndicatorPositionChangedListener onIndicatorPositionChangedListener =new OnIndicatorPositionChangedListener() {@Overridepublic void onIndicatorPositionChanged(@NotNull Point point) {// point即为用户位置} };③ 移动相机到用户的位置:
移动相机方法参见 5.相机动画插件 部分,在onIndicatorPositionChanged回调中根据point参数进行移动即可。
需要注意的是,onIndicatorPositionChanged监听器在remove前会持续回调,需编写相关移动相机的条件,否则地图移动手势将会失效。
官网教程:
https://docs.mapbox.com/android/maps/guides/user-location/
8. 地图标记插件
Mapbox提供了annotationPlugin 插件供用户在地图上快捷添加标记。添加标记的方法如下所示
注意:以下标记的添加需要在地图初始化加载完成后进行,即style加载完后进行。
[举例] 向地图添加点标记(可以显示icon + text)
// 注册点标记管理器 PointAnnotationManager pointAnnotationManager = (PointAnnotationManager)annotationPlugin .createAnnotationManager(AnnotationType.PointAnnotation, null);/*** 在地图中添加Point类型标记* @param longitude 添加坐标X* @param latitude 添加坐标Y*/ public void addPointAnnotationInMap(int drawable, double longitude, double latitude) {if(annotationPlugin == null){return;}if (pointAnnotationManager == null) {pointAnnotationManager = (PointAnnotationManager)annotationPlugin .createAnnotationManager(AnnotationType.PointAnnotation, null);}// Set options for the resulting symbol layer.PointAnnotationOptions pointAnnotationOptions = new PointAnnotationOptions().withPoint(Point.fromLngLat(longitude, latitude)).withIconImage(BitmapUtil.getBitmapFromDrawable(mContext, drawable));// Add the pointAnnotation to the map.pointAnnotationManager .create(pointAnnotationOptions); }pointAnnotationOptions中还有很多方法可以设置,这里不再举例。
更多标记类型:
https://docs.mapbox.com/android/maps/guides/annotations/annotations/
除次之外Mapbox还提供了ViewAnnotation,用户可以利用此添加自定义样式的标记,添加方法如下所示:
ViewAnnotationManager viewAnnotationManager = mMapView.getViewAnnotationManager();以下方法举例了如何在ViewAnnotationManager添加自定义的View标记:
/*** 在地图中添加View标记 [需补充代码后使用]* @param longitude 添加坐标* @param latitude 添加坐标* @param onClickListener view点击回调*/public void addViewAnnotationInMap(double longitude, double latitude, View.OnClickListener onClickListener) {if (viewAnnotationManager == null) {viewAnnotationManager = mMapView.getViewAnnotationManager();} // View markView = viewAnnotationManager.addViewAnnotation(R.layout.item_map_image_view, // view的layout id // new ViewAnnotationOptions.Builder() // .geometry(Point.fromLngLat(longitude, latitude)) // .allowOverlap(true) // 允许markView重叠 // .build());// 初始化 layout中的组件 markView.findViewById(R.id.xxx)// ...}上述两种添加方式在 少量(<200) 标记时不会造成地图组件卡顿(应设备而异),若要添加大量标记,上述方法性能问题不容乐观。
mapbox对此提供了 style layer 的解决方案,用于添加 大量图标 时的性能保证。
style layer 添加地图标记,并实现聚类的方法见下一篇文章:Android地图—— Mapbox 10.3.0 聚类标签实现。
总结
以上是生活随笔为你收集整理的Android地图—— Mapbox 10.3.0 接入与基础使用的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 重学JavaScript深入理解系列(六
- 下一篇: 小程序和Android开发,微信小程序和