半栈工程师程序员Android

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

2018-05-19  本文已影响273人  Master_文
前段时间搞高德地图,集成地图后,发现如果把地图这块放在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

上一篇下一篇

猜你喜欢

热点阅读