美文网首页半栈工程师程序员Android
几行代码实现高德地图的高级用法

几行代码实现高德地图的高级用法

作者: Master_文 | 来源:发表于2018-05-19 14:13 被阅读273次
    前段时间搞高德地图,集成地图后,发现如果把地图这块放在view里面,不便于后期的维护,想着封装一个,把地图有关的方法,专门放一个类,同时也方便以后的偷懒☺.Let's Go!
    • 显示地图
    public class MapActivity extends AppCompatActivity {
        @InjectView(R.id.mapView)
        MapView mMapView;
        private AMap aMap;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_map);
            // 使用黄油刀注解找控件
            ButterKnife.inject(this);
            initMap(savedInstanceState);
        }
    
        private void initMap(Bundle savedInstanceState) {
            mMapView.onCreate(savedInstanceState);
            aMap = null;
            if (aMap == null) {
                aMap = mMapView.getMap();
            }
            // 显示地图
            MapUtil.getInstance().initMap(aMap, this);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            // 在activity执行onDestroy时执行mMapView.onDestroy(),销毁地图
            mMapView.onDestroy();
        }
    
        @Override
        public void onResume() {
            super.onResume();
            // 在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图
            mMapView.onResume();
        }
    
    
        @Override
        public void onPause() {
            super.onPause();
            // 在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制
            mMapView.onPause();
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            // 在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
            mMapView.onSaveInstanceState(outState);
        }
    
    }
    
    除了地图相关的配置外,你只需要 MapUtil.getInstance().initMap(aMap, this);一行代码就可以实现,够简洁吧!下面我们看下,内部的实现
        // 单例没啥好说的 
        private static MapUtil sMapUtil;
        private LatLng  mLatLng;
    
        private MapUtil() {
    
        }
    ![![微信图片_20180519135100.jpg](https:https://img.haomeiwen.com/i5286943/34dfb6ace9ea966b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ](https:https://img.haomeiwen.com/i5286943/5ea74273e21ca41f.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
        public static MapUtil getInstance() {
            if (sMapUtil == null) {
                synchronized (MapUtil.class) {
                    if (sMapUtil == null) {
                        sMapUtil = new MapUtil();
                    }
                }
            }
            return sMapUtil;
        }
    
        // 初始化地图,关键代码
        public MapUtil initMap(AMap aMap, Context context) {
            this.aMap = aMap;
            this.mContext = context;
            mlocationClient = new AMapLocationClient(context);
            //初始化定位参数
            mLocationOption = new AMapLocationClientOption();
            //设置定位监听
            mlocationClient.setLocationListener(this);
            //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(3000);
            //设置定位参数
            mlocationClient.setLocationOption(mLocationOption);
            // 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
            // 注意设置合适的定位时间的间隔(最小间隔支持为1000ms),并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后,在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
            //启动定位
            mlocationClient.startLocation();
            // TODO: 2018/5/13 地图的层级大小,可以对外暴露 
            aMap.moveCamera(CameraUpdateFactory.zoomTo(19));
            // 显示定位蓝点
            initPoint();
            // 去掉右边缩放按钮
            aMap.getUiSettings().setZoomControlsEnabled(false);
            aMap.setOnCameraChangeListener(this);
            return this;
        }
    
    // 自定义定位蓝点
        public void initPoint() {
            MyLocationStyle myLocationStyle;
            myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
            myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
            // 设置边框的颜色
            myLocationStyle.strokeColor(Color.TRANSPARENT);
            // 设置边框的填充色
            myLocationStyle.radiusFillColor(Color.TRANSPARENT);
            // 设置定位点图片
            myLocationStyle.myLocationIcon(getBitmapDescriptor(R.mipmap.icon_location_blue));
            // 定位一次,且将视角移动到地图中心点
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
            aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
            //aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
            aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
            // 因为模式问题,所以要手动调用
            if (mLatLng != null) {
                aMap.moveCamera(CameraUpdateFactory.changeLatLng(mLatLng));
            }
        }
    
    • 绘制Marker点
    private void initMap(Bundle savedInstanceState) {
            mMapView.onCreate(savedInstanceState);
            aMap = null;
            if (aMap == null) {
                aMap = mMapView.getMap();
            }
            // 显示地图,设置地图回调
            MapUtil.getInstance().initMap(aMap, this).setMapRefreshListener(this);
        }
    
        public void drawMarker(LatLng latLng) {
            // 模拟数据集合
            List<LatLng> markerList = new ArrayList<>();
            for (int i = 0; i < 4; i++) {
                double longitude = latLng.longitude + ((i + 1) * 0.0001);
                double latitude = latLng.latitude + ((i + 1) * 0.0001);
                markerList.add(new LatLng(latitude, longitude));
            }
            // 绘制Marker集合
            MapUtil.getInstance().addAllMarker(markerList);
            // 绘制Marker点
            MapUtil.getInstance().addMarker(latLng);
        }
    
        /**
         * 得到经纬度
         * @param latLng
         */
        @Override
        public void getLatLng(LatLng latLng) {
            // 绘制marker
            drawMarker(latLng);
        }
    
    

    MapUtil

     public void addAllMarker(List<LatLng> latLngList) {
            for (LatLng latLng : latLngList) {
                addMarker(latLng);
            }
        }
    
        public void addMarker(LatLng latLng) {
            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(latLng);
            // TODO: 2018/5/13 如果是复杂的,可以把布局转成bitmap
            //        View view = View.inflate(mContext, R.layout.marker, null);
            //        Bitmap bitmap = convertViewToBitmap(view);
    
            // 自定义图片
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
                    .decodeResource(mContext.getResources(), R.mipmap.icon_taskcar_get)));
            //        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
    
            Marker marker = aMap.addMarker(markerOptions);
            mMarkerSparseArray.put(mMarkerSparseArray.size(), marker);
            marker.showInfoWindow();
            // 是否需要显示弹窗
            infoWindow();
        }
    
    
    • Marker点的点击事件
    我就是怎么强大
    // 由于第一次点击也会走地图的回调,所以要加个开关
        private boolean toggle = false;
    
        // 定义 Marker [图片上传中...(31bcedde8ed5d0abf39d165177c83736.gif-b70360-1526708414566-0)]
    点击事件监听
        AMap.OnMarkerClickListener markerClickListener = new AMap.OnMarkerClickListener() {
            // marker 对象被点击时回调的接口
            // 返回 true 则表示接口已响应事件,否则返回false
            @Override
            public boolean onMarkerClick(Marker marker) {
                mMarker = marker;
                toggle = true;
                MapUtil.getInstance().addInfoWindow(marker);
                return false;
            }
        };
    
     private void initMap(Bundle savedInstanceState) {
            mMapView.onCreate(savedInstanceState);
            // 使用黄油刀注解找控件
            aMap = null;
            if (aMap == null) {
                aMap = mMapView.getMap();
            }
            // 显示地图,设置地图回调
            MapUtil.getInstance().initMap(aMap, this).setMapRefreshListener(this);
            // 实现地图的监听
            aMap.setOnMapClickListener(new AMap.OnMapClickListener() {
                @Override
                public void onMapClick(LatLng latLng) {
                    if (!toggle && mMarker != null) {
                        MapUtil.getInstance().removeInfoWindow(mMarker);
                        mMarker = null;
                    }
                    toggle = false;
                }
            });
            // 实现marker的监听
            aMap.setOnMarkerClickListener(markerClickListener);
        }
    

    MapUtil

    /**
         * 添加移除infoWindow
         * @param marker
         */
        public void addInfoWindow(Marker marker) {
            marker.setInfoWindowEnable(true);
        }
    
        /**
         * 移除infoWindow
         * @param marker
         */
        public void removeInfoWindow(Marker marker) {
            marker.setInfoWindowEnable(false);
        }
    
    绘制矩形
     /**
         * 得到经纬度
         *
         * @param latLng
         */
        @Override
        public void getLatLng(LatLng latLng) {
            // 绘制marker
            drawMarker(latLng);
            // 绘制线
            drawRectangle(latLng);
        }
    
     private void drawRectangle(LatLng latLng) {
            MapUtil.getInstance().addRectangle(latLng);
        }
    

    MapUtil

    public void addRectangle(LatLng latLng) {
            // 绘制一个长方形
            aMap.addPolygon(new PolygonOptions()
                    .addAll(createRectangle(latLng, 0.0001, 0.0001))
                    .fillColor(Color.parseColor("#FFCBCB"))
                    // 线的宽度取消
                    .strokeWidth(0)
            );
            // 虚线组成一个长方形
            aMap.addPolyline(new PolylineOptions()
                    .addAll(createRectangle(latLng, 0.0001, 0.0001))
                    .width(10)
                    .setDottedLine(true)
                    .color(Color.parseColor("#F45A5A")));
        }
    
        public void addRectangle(List<LatLng> latLngList) {
            // 绘制一个长方形
            aMap.addPolygon(new PolygonOptions()
                    .addAll(latLngList)
                    .fillColor(Color.parseColor("#4DBDEDFF"))
                    // 线的宽度取消
                    .strokeWidth(0)
            );
            // 虚线组成一个长方形
            aMap.addPolyline(new PolylineOptions()
                    .addAll(latLngList)
                    .width(10)
                    .setDottedLine(true)
                    .color(Color.parseColor("#3BC3F5")));
        }
    
        /**
         * 生成一个长方形的四个坐标点
         */
        private List<LatLng> createRectangle(LatLng center, double halfWidth, double halfHeight) {
            List<LatLng> latLngs = new ArrayList<LatLng>();
            // TODO: 2018/5/19 添加最后一个点,组成闭合,不然会少一边 
            latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
            // 矩形的四个点
            latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
            latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude + halfWidth));
            latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude + halfWidth));
            latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
            return latLngs;
        }
    
    这里要注意:画矩形要给5个点,第一个和最后一个点一样,文档上是4个点,会少一边
    移动指定距离刷新地图
    @Override
        public void onCameraChange(CameraPosition cameraPosition) {
    
        }
    
        @Override
        public void onCameraChangeFinish(CameraPosition cameraPosition) {
            LatLng currentLatlng = cameraPosition.target;
            double distance = AMapUtils.calculateLineDistance(preLatlng, currentLatlng);
            totalDistance = distance;
            Log.d(TAG, "onCameraChange: 距离" + totalDistance);
            if (totalDistance >= REFRESH_DISTANCE) {
                if (firstChange) {
                    firstChange = false;
                    return;
                }
                preLatlng = currentLatlng;
                Log.d(TAG, "onCameraChange: 要刷新了");
                totalDistance = 0;
                if (mMapListener != null) {
                    mMapListener.refresh();
                }
            }
        }
    
    监听地图中心点的位置,和起始点位置,获取距离,如果大于,就把当前点记录,这里要注意的是,刚开始的时候位置会偏移很大,排除第一次的
    • 重置指南针
    image

    MapActivity没什么好说的

    @OnClick(R.id.iv_location)
        public void onViewClicked() {
            MapUtil.getInstance().initPoint();
        }
    

    MapUtil

    // 开启指南针
    // 初始化地图,关键代码
        public MapUtil initMap(AMap aMap, Context context, int getZoomB) {
            this.aMap = aMap;
            this.mContext = context;
            mlocationClient = new AMapLocationClient(context);
            //初始化定位参数
            mLocationOption = new AMapLocationClientOption();
            //设置定位监听
            mlocationClient.setLocationListener(this);
            //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(3000);
            //设置定位参数
            mlocationClient.setLocationOption(mLocationOption);
            // 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
            // 注意设置合适的定位时间的间隔(最小间隔支持为1000ms),并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后,在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
            //启动定位
            mlocationClient.startLocation();
            // 显示定位蓝点
            initPoint();
            // 去掉右边缩放按钮
            aMap.getUiSettings().setZoomControlsEnabled(false);
            aMap.setOnCameraChangeListener(this);
            // 开启指南针
            aMap.getUiSettings().setCompassEnabled(true);
            return this;
        }
    
     // 自定义定位蓝点
        public void initPoint() {
            MyLocationStyle myLocationStyle;
            myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
            myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
            // 设置边框的颜色
            myLocationStyle.strokeColor(Color.TRANSPARENT);
            // 设置边框的填充色
            myLocationStyle.radiusFillColor(Color.TRANSPARENT);
            // 设置定位点图片
            myLocationStyle.myLocationIcon(getBitmapDescriptor(R.mipmap.icon_location_blue));
            // 定位一次,且将视角移动到地图中心点
            myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
            aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
            //aMap.getUiSettings().setMyLocationButtonEnabled(true);设置默认定位按钮是否显示,非必需设置。
            aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
            // 因为模式问题,所以要手动调用
            if (mLatLng != null) {
                aMap.moveCamera(CameraUpdateFactory.changeLatLng(mLatLng));
            }
            // 地图的层级大小
            aMap.moveCamera(CameraUpdateFactory.zoomTo(getZoomB));
            // TODO: 2018/5/21 0021  重置指南针位置,找了好久
            if (mLatLng != null) {
                float bearing = 0.0f;  // 地图默认方向
                float tilt = 0.0f;  // 地图默认方向
                aMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(mLatLng, getZoomB, tilt, bearing)));
            }
        }
    

    文末:主要提供一种思路,如果有不对或者可以改进的,欢迎下方留言

    百度网盘地址:https://pan.baidu.com/s/1KiCA5y9FhxPxPMQObD9SQg

    相关文章

      网友评论

      • rulf:大神,帮我解决bug
      • 骑小猪看流星:大兄弟为什么不放在github哦⊙∀⊙!
        Master_文:@骑小猪看流星 老哥,我这个类没有放到github,因为这个只是一个简单的封装逻辑,类在百度网盘里,activity是对应的调用
        骑小猪看流星:@Master_文 大兄弟 你的这个项目我clone下来后 发现没有这个工具类 太尴尬了吧。。。
        Master_文:@骑小猪看流星 这个代码只是零时写的,github地址:https://github.com/GongWnbo/SuperRecycleView
        上面的没写博客,时间不够,github上面的功能也没具体说明。。。。

      本文标题:几行代码实现高德地图的高级用法

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