Osheep

时光不回头,当下最重要。

Android高德地图填坑

项目中用到地图的地方越来越多,从O2O商城、出行、交通、单车等无处不在使用地图,以下是在多个项目中集成高德地图常用的几个功能点,及填坑。

定位功能

使用了最新的SdkAndroid_Map3D_SDK_V5.1.0_20170518.jar,与之前的sdk的定位回调有部分差异。

  1. 小蓝点策略
    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,小蓝点的移动位置由我们来控制。

  2. 定位的实现
    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

  1. 始终固定在屏幕中心位置的点
    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);
    }
  2. 给中心点添加跳跃动画
    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();
    }   
    }
  3. 添加多个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的点击事件
  4. 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();
        }
    }

导航路线的绘制和清除

使用了Sdk里的路线导航确实可以绘制,但是如果我想在当前页面再次绘制某个点,除了使用aMap.clear()方法,其他的均无效果。这样就会导致一个问题,已经绘制到地图上的信息均被清除,导致体验性很差。于是有了第二种绘制路线的方法:使用Web服务API

  1. 根据返回的数据封装成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;
                 }
             }
         }
     }
    }
  2. 循环组装成一个所有路线的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);
    }
  3. 然后就可以绘制了
    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));
     }
  4. 清除再绘制
    if (polyline != null) {
        polyline.remove();
        polyline = null;
    }

    这样我们就轻松的完成了路线规划的绘制和清除,而不用考虑地图上其他的元素。

点赞