Android高德地图填坑

作者: 倔强的炉包 | 来源:发表于2017-06-23 11:27 被阅读2723次

    项目中用到地图的地方越来越多,从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,小蓝点的移动位置由我们来控制。

    1. 定位的实现
    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);
        }
    
    1. 给中心点添加跳跃动画
    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();
        }   
    }
    
    1. 添加多个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的点击事件
    
    1. 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();
            }
        }
    
    1. 移除Marker
      移除marker有两种方式,一个是remove,一个是destory,对于在地图上需要大量移除并添加新的marker来说,慎用destory,否则会出现marker在地图上的各种问题。
    if (marker != null) {
            marker.remove;
            marker = null;
    }
    

    导航路线的绘制和清除

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

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

    fragment显示地图 没有完全释放

    fragment中第一次显示地图没问题,但是在退出程序重新打开地图会发现地图定位失败,并且定位图层和缩放图层都不见了。一开始想到的是地图没有释放干净,然后就把所有的地图图层全部remove,并且setXXX=null,然后并没有什么效果。后来把fragment的初始化方式更改为new Instance()的方式就解决了。

    相关文章

      网友评论

      • 神经病人思路广:新加的那三个小蓝点不能定位,你试过了吗?
      • Love零O:定位的回调onMyLocationChange一直在执行,是用isFirst来控制的吗
        倔强的炉包:不一定,看你的使用场景。我这里只是为了把定位点移到地图中心。

      本文标题:Android高德地图填坑

      本文链接:https://www.haomeiwen.com/subject/aetccxtx.html