AndroidAndroid开发程序员

Android高德地图填坑

2017-06-23  本文已影响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()的方式就解决了。

上一篇下一篇

猜你喜欢

热点阅读