项目中用到地图的地方越来越多,从O2O商城、出行、交通、单车等无处不在使用地图,以下是在多个项目中集成高德地图常用的几个功能点,及填坑。
定位功能
使用了最新的SdkAndroid_Map3D_SDK_V5.1.0_20170518.jar,与之前的sdk的定位回调有部分差异。
- 小蓝点策略
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);//只定位一次。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE) ;//定位一次,且将视角移动到地图中心点。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW) ;//连续定位、且将视角移动到地图中心点,定位蓝点跟随设备移动。(1秒1次定位)
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE);//连续定位、且将视角移动到地图中心点,地图依照设备方向旋转,定位点会跟随设备移动。(1秒1次定位)
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)默认执行此种模式。
//以下三种模式从5.1.0版本开始提供
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点,定位点依照设备方向旋转,并且蓝点会跟随设备移动。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);//连续定位、蓝点不会移动到地图中心点,并且蓝点会跟随设备移动。
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_MAP_ROTATE_NO_CENTER);//连续定位、蓝点不会移动到地图中心点,地图依照设备方向旋转,并且蓝点会跟随设备移动。
增加的比较有用的是LOCATION_TYPE_FOLLOW_NO_CENTER
,小蓝点的移动位置由我们来控制。
- 定位的实现
aMap.setOnMyLocationChangeListener(this);
@Override
public void onMyLocationChange(Location location) {
if (location != null) {
Bundle bundle = location.getExtras();
if (bundle != null) {
mLocationLatitude = location.getLatitude();
mLocationLongitude = location.getLongitude();
mLocationLatitude = Double.valueOf(df.format(mLocationLatitude));
mLocationLongitude = Double.valueOf(df.format(mLocationLongitude));
if (isFirst) {
if (mLocationLatitude > 0 && mLocationLongitude > 0) {
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(new LatLng(mLocationLatitude, mLocationLongitude), 17);
aMap.moveCamera(cu);
} else {
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(new LatLng(Constant.DEFAULT_LATITUDE, Constant.DEFAULT_LONGITUDE), 17);
aMap.moveCamera(cu);
}
isFirst = false;
}
} else {
ToastUtil.showShort(mContext, "定位失败,请检查您的定位权限");
}
}
}
Marker
- 始终固定在屏幕中心位置的点
private void addMarkerInScreenCenter() {
if (screenMarker == null) {
screenMarker = aMap.addMarker(new MarkerOptions().zIndex(2)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_screen_location)));
}
screenMarker.setAnchor(0.5f, 1.0f);
LatLng latLng = aMap.getCameraPosition().target;
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
screenMarker.setPositionByPixels(screenPosition.x, screenPosition.y);
screenMarker.setClickable(false);
}
- 给中心点添加跳跃动画
public void screenMarkerJump(AMap aMap, Marker screenMarker) {
if (screenMarker != null) {
final LatLng latLng = screenMarker.getPosition();
Point point = aMap.getProjection().toScreenLocation(latLng);
point.y -= Utils.dip2px(mContext, 20);
LatLng target = aMap.getProjection()
.fromScreenLocation(point);
//使用TranslateAnimation,填写一个需要移动的目标点
Animation animation = new TranslateAnimation(target);
animation.setInterpolator(new Interpolator() {
@Override
public float getInterpolation(float input) {
// 模拟重加速度的interpolator
if (input <= 0.5) {
return (float) (0.5f - 2 * (0.5 - input) * (0.5 - input));
} else {
return (float) (0.5f - Math.sqrt((input - 0.5f) * (1.5f - input)));
}
}
});
//整个移动所需要的时间
animation.setDuration(600);
//设置动画
screenMarker.setAnimation(animation);
//开始动画
screenMarker.startAnimation();
}
}
- 添加多个Marker标记
获取到需要添加的Marker列表,循环添加到地图上。
for (int i = 0; i < mParkingListBeen.size(); i++) {
LatLng latLng = new LatLng(mParkingListBeen.get(i).getLatitude(), mParkingListBeen.get(i).getLongitude());
Marker marker = aMap.addMarker(new MarkerOptions()
.title("i")
.anchor(0.5f, 0.92f)
.position(latLng).zIndex(1)
.icon(BitmapDescriptorFactory
.fromBitmap(mParkingBitmap))
.draggable(false));
marker.setObject(mParkingListBeen.get(i));
mBikeMarkers.add(marker);
aMap.setOnMarkerClickListener(this);
}
需要注意的以下几点:
1.Marker的bitmap要提前初始化,添加Marker的时候使用。
2.Marker需要点击弹窗,必须设置title属性
3.anchor的默认值是0.5f和1.0f,是相对x和y方向的偏移比例
4.zIndex设置z轴的重叠顺序
5.Marker的信息可以setObject(),获取的时候getObject()并进行强制转换
6.添加Marker的点击事件
- Marker的生长动画
public void startGrowAnimation(AMap aMap, Marker growMarker) {
try {
if (growMarker != null) {
Animation animation = new ScaleAnimation(0, 1, 0, 1);
animation.setInterpolator(new LinearInterpolator());
//整个移动所需要的时间
animation.setDuration(150);
//设置动画
growMarker.setAnimation(animation);
//开始动画
growMarker.startAnimation();
}
} catch (Exception e) {
e.printStackTrace();
}
}
- 移除Marker
移除marker有两种方式,一个是remove
,一个是destory
,对于在地图上需要大量移除并添加新的marker来说,慎用destory
,否则会出现marker在地图上的各种问题。
if (marker != null) {
marker.remove;
marker = null;
}
导航路线的绘制和清除
使用了Sdk里的路线导航确实可以绘制,但是如果我想在当前页面再次绘制某个点,除了使用aMap.clear()
方法,其他的均无效果。这样就会导致一个问题,已经绘制到地图上的信息均被清除,导致体验性很差。于是有了第二种绘制路线的方法:使用Web服务API。
- 根据返回的数据封装成model
public class WalkingPathBean {
private String status;
private String info;
private String infocode;
private String count;
private RouteBean route;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getInfocode() {
return infocode;
}
public void setInfocode(String infocode) {
this.infocode = infocode;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
public RouteBean getRoute() {
return route;
}
public void setRoute(RouteBean route) {
this.route = route;
}
public static class RouteBean {
private String origin;
private String destination;
private List<PathsBean> paths;
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public List<PathsBean> getPaths() {
return paths;
}
public void setPaths(List<PathsBean> paths) {
this.paths = paths;
}
public static class PathsBean {
private String distance;
private String duration;
private List<StepsBean> steps;
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public List<StepsBean> getSteps() {
return steps;
}
public void setSteps(List<StepsBean> steps) {
this.steps = steps;
}
public static class StepsBean {
private String polyline;
public String getPolyline() {
return polyline;
}
public void setPolyline(String polyline) {
this.polyline = polyline;
}
}
}
}
}
- 循环组装成一个所有路线的list
if (size > 0) {
String distance = walkingPathBean.getContent().getRoute().getPaths().get(0).getDistance();
String duration = walkingPathBean.getContent().getRoute().getPaths().get(0).getDuration();
List<LatLng> latLngs = new ArrayList<>();
int steps = walkingPathBean.getContent().getRoute().getPaths().get(0).getSteps().size();
latLngs.add(orignLat);
for (int i = 0; i < steps; i++) {
String polylines = walkingPathBean.getContent().getRoute().getPaths().get(0).getSteps().get(i).getPolyline();
String[] latlngArr = polylines.split(";");
if (latlngArr.length > 0) {
for (String lanLon : latlngArr) {
String[] latlng_str = lanLon.split(",");
if (latlng_str.length > 1) {
LatLng mLatLng = new LatLng(Double.valueOf(latlng_str[1]), Double.valueOf(latlng_str[0]));
latLngs.add(mLatLng);
}
}
}
}
latLngs.add(destLat);
}
- 然后就可以绘制了
polyline = aMap.addPolyline(new PolylineOptions().
addAll(latLngs).width(14f).color(Color.parseColor("#CEE00E")));
zoomToSpan(latLngs);
//根据屏幕的位置对路线进行适应屏幕的缩放
private void zoomToSpan(List<LatLng> latLngs) {
LatLngBounds.Builder b = LatLngBounds.builder();
for (LatLng latLng : latLngs) {
b.include(latLng);
}
LatLngBounds bounds = b.build();
int top_padding = Utils.dip2px(mContext, 96 + 70);
int bottom_padding = Utils.dip2px(mContext, 40 + 20 + 10);
int left_right_padding = Utils.dip2px(mContext, 15);
aMap.moveCamera(CameraUpdateFactory
.newLatLngBoundsRect(bounds, left_right_padding, left_right_padding, top_padding, bottom_padding));
}
- 清除再绘制
if (polyline != null) {
polyline.remove();
polyline = null;
}
这样我们就轻松的完成了路线规划的绘制和清除,而不用考虑地图上其他的元素。
---------------------------------------2017.12.18更新------------------------------------
fragment显示地图 没有完全释放
fragment中第一次显示地图没问题,但是在退出程序重新打开地图会发现地图定位失败,并且定位图层和缩放图层都不见了。一开始想到的是地图没有释放干净,然后就把所有的地图图层全部remove,并且setXXX=null,然后并没有什么效果。后来把fragment的初始化方式更改为new Instance()的方式就解决了。
网友评论