1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android高德地图绘制多边形_Android安卓高德地图实现多边形绘制与编辑

android高德地图绘制多边形_Android安卓高德地图实现多边形绘制与编辑

时间:2020-03-04 08:11:46

相关推荐

android高德地图绘制多边形_Android安卓高德地图实现多边形绘制与编辑

需求:使用高德地图api实现多边形的绘制与编辑,从而实现圈中房屋的效果。

在js中有相关插件,效果很好。点我跳转

但是在高德开放平台中并未找到安卓ios的相关插件或者方法,于是提交工单,5个工作日才能回复,算了不等了,自己写吧!

思路:

1.首先根据当前定位的点绘制一个矩形,在矩形的四个顶点(LatLng)创建Marker,并给四个顶点初始化一个状态(MyLatLng.ABLE)和一个索引值。

2.计算矩形四边的中点经纬度(LatLng),四个中点创建Marker,并给四个顶点初始化一个状态(MyLatLng.UNABLE)和一个索引值。

3.绘制多边形样式,并调用AMap.addPolygon方法创建多边形。

4.aMap.setOnMarkerDragListener给Marker添加拖拽事件

5.在onMarkerDragStart方法移除拖拽的Marker

6.在onMarkerDragEnd方法添加新的Marker并判断该点左右两个Marker的状态:如果状态为MyLatLng.ABLE,则表示该点拖拽后需要在该点两侧创建新Marker。如果状态为MyLatLng.UNABLE则不需要创建新的点,而是替换两侧的点的坐标(该坐标为新点到两侧点的中间点)。

7、重新根据新的点绘制多边形

效果图

444.png

代码:

1.集成高德地图和申请位置权限就不说了

2.初始化地图

/**

* 初始化地图

*/

private void initMap() {

if (aMap == null) {

aMap = mMapView.getMap();

MyLocationStyle myLocationStyle;

myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。

myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);

myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。

aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style

aMap.setMinZoomLevel(20);//不让用户缩放地图

aMap.moveCamera(CameraUpdateFactory.zoomTo(20));

mlocationClient = new AMapLocationClient(this.getApplicationContext());

locationOption = getDefaultOption();

mlocationClient.setLocationOption(locationOption);

mlocationClient.setLocationListener(locationListener);

// 启动定位

mlocationClient.startLocation();

}

}

/**

* 设置默认的定位参数

*/

private AMapLocationClientOption getDefaultOption() {

AMapLocationClientOption mOption = new AMapLocationClientOption();

mOption.setLocationMode(

AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式

mOption.setGpsFirst(false);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭

mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效

mOption.setInterval(300000);//可选,设置定位间隔。默认为2秒

mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true

mOption.setOnceLocation(true);//可选,设置是否单次定位。默认是false

mOption.setOnceLocationLatest(false);//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用

AMapLocationClientOption.setLocationProtocol(

AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP

mOption.setWifiScan(

true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差

return mOption;

}

3.定位的监听

/**

* 定位监听

*/

AMapLocationListener locationListener = new AMapLocationListener() {

@Override

public void onLocationChanged(AMapLocation amapLocation) {

if (null != amapLocation) {

//errCode等于0代表定位成功,其他的为定位失败,具体的可以参照官网定位错误码说明

if (amapLocation.getErrorCode() == 0) {

latitude = amapLocation.getLatitude();

longitude = amapLocation.getLongitude();

aMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(latitude, longitude)));

createRectangle();

}

}

}

};

4.绘制可编辑多边形并添加拖拽事件

/**

* 绘制可编辑多边形

*/

private void createRectangle() {

if (latitude != null && longitude != null) {

//创建一个中心点坐标

DPoint centerPoint = new DPoint();

//设置中心点纬度

centerPoint.setLatitude(latitude);

//设置中心点经度

centerPoint.setLongitude(longitude);

//初始化数据

initRectangle();

//初始化多边形的polygonOptions

for (int i = 0; i < allLatLngs.size(); i++) {

polygonOptions.add(allLatLngs.get(i).getLatLng());

}

//初始化8个点的marker

addMarker(true);

//绘制区域颜色

createAreaStyle();

//创建多边形

aMap.addPolygon(polygonOptions);

//添加拖拽事件(必须要长按才可以拖拽)

aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {

@Override

public void onMarkerDragStart(Marker marker) {

//开始拖拽时,把集合里的该点删除掉

int i = (int) marker.getObject();

Log.e(TAG, "移除第" + i + "个");

allLatLngs.remove(i);

refreshPolygonOptions();

}

@Override

public void onMarkerDrag(Marker marker) {

}

@Override

public void onMarkerDragEnd(Marker marker) {

//拖拽结束时,创建新点

allLatLngs.add((int) marker.getObject(), new MyLatLng(new LatLng(marker.getPosition().latitude, marker.getPosition().longitude), MyLatLng.ABLE));

//判断是否需要创建新的点

if (!isCreateMarker(marker)) {

//不需要

//如果拖拽的是状态为0的点,则不需要创建新的点,而是替换两侧的点的坐标(注意是替换set方法)。

replaceTwoMarker(marker);

refreshPolygonOptions();

addMarker(true);

createAreaStyle();

aMap.addPolygon(polygonOptions);

} else {

//需要

refreshPolygonOptions();

addMarker(true);

createAreaStyle();

aMap.addPolygon(polygonOptions);

//在拖拽点两侧添加maker

addTwoMarker(marker);

addMarker(false);

}

}

});

}

}

/**

* 生成一个长方形的四个坐标点

*/

private void initRectangle() {

BigDecimal currentLatBd = new BigDecimal(latitude);

BigDecimal currentLongBd = new BigDecimal(longitude);

BigDecimal b3 = new BigDecimal("0.0002");

BigDecimal b4 = new BigDecimal("0.0003");

MyLatLng latLng1 = new MyLatLng(new LatLng(currentLatBd.subtract(b3).doubleValue(), currentLongBd.add(b3).doubleValue()), MyLatLng.ABLE);

MyLatLng latLng2 = new MyLatLng(new LatLng(currentLatBd.subtract(b3).doubleValue(), currentLongBd.subtract(b3).doubleValue()), MyLatLng.ABLE);

MyLatLng latLng3 = new MyLatLng(new LatLng(currentLatBd.add(b3).doubleValue(), currentLongBd.subtract(b3).doubleValue()), MyLatLng.ABLE);

MyLatLng latLng4 = new MyLatLng(new LatLng(currentLatBd.add(b3).doubleValue(), currentLongBd.add(b3).doubleValue()), MyLatLng.ABLE);

MyLatLng latLng12 = getCenterPoint(latLng1, latLng2);

MyLatLng latLng23 = getCenterPoint(latLng2, latLng3);

MyLatLng latLng34 = getCenterPoint(latLng3, latLng4);

MyLatLng latLng41 = getCenterPoint(latLng4, latLng1);

allLatLngs.add(latLng1);

allLatLngs.add(latLng12);

allLatLngs.add(latLng2);

allLatLngs.add(latLng23);

allLatLngs.add(latLng3);

allLatLngs.add(latLng34);

allLatLngs.add(latLng4);

allLatLngs.add(latLng41);

//设置显示范围(如果不需要,把后面的代码注释掉)

LatLngBounds latLngBounds = new LatLngBounds(

new LatLng(currentLatBd.subtract(b4).doubleValue(), currentLongBd.subtract(b4).doubleValue()),

new LatLng(currentLatBd.add(b4).doubleValue(), currentLongBd.add(b4).doubleValue()));

aMap.setMapStatusLimits(latLngBounds);

}

/**

* 根据总得点集合,刷新polygonOptions集合的数据

*/

private void refreshPolygonOptions() {

if (polygonOptions.getPoints().size() != MyLatLng.UNABLE) {

polygonOptions.getPoints().clear();

}

for (int i = 0; i < allLatLngs.size(); i++) {

polygonOptions.add(allLatLngs.get(i).getLatLng());

}

}

/**

* 判断拖拽的点松手后是否需要创建新点

*/

private boolean isCreateMarker(Marker marker) {

int index = (int) marker.getObject();

if (index == 0) {

Log.e(TAG, "需要添加两个Marker");

return false;

}

if (index == allLatLngs.size() - 1) {

if (allLatLngs.get(index - 1).getState() == MyLatLng.ABLE && allLatLngs.get(0).getState() == MyLatLng.ABLE) {

Log.e(TAG, "需要添加两个Marker");

return true;

}

}

if (allLatLngs.get(index - 1).getState() == MyLatLng.ABLE) {

Log.e(TAG, "需要添加两个Marker");

return true;

}

Log.e(TAG, "不需要添加两个Marker");

return false;

}

/**

* 在拖拽点两侧添加maker

*/

private void addTwoMarker(Marker marker) {

int index = (int) marker.getObject();

if (index == 0) {

//判断拖拽的点两侧点的状态,如果为1,则可以新建两个点

if (allLatLngs.get(1).getState() == MyLatLng.ABLE && allLatLngs.get(allLatLngs.size() - 1).getState() == MyLatLng.ABLE) {

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(0), allLatLngs.get(1));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(0), allLatLngs.get(allLatLngs.size() - 1));

allLatLngs.add(1, centerPoint1);

allLatLngs.add(allLatLngs.size() - 1, centerPoint2);

Log.e(TAG, "在第" + 1 + "个添加marker");

Log.e(TAG, "在第" + (allLatLngs.size() - 1) + "个添加marker");

}

return;

}

if (index == allLatLngs.size() - 1) {

if (allLatLngs.get(index - 1).getState() == MyLatLng.ABLE && allLatLngs.get(0).getState() == MyLatLng.ABLE) {

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(index - 1), allLatLngs.get(index));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(index), allLatLngs.get(0));

allLatLngs.add(index, centerPoint1);

allLatLngs.add(index + 2, centerPoint2);

Log.e(TAG, "在第" + index + "个添加marker");

Log.e(TAG, "在第" + (index + 2) + "个添加marker");

return;

}

}

if (allLatLngs.get(index - 1).getState() == MyLatLng.ABLE && allLatLngs.get(index + 1).getState() == MyLatLng.ABLE) {

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(index - 1), allLatLngs.get(index));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(index), allLatLngs.get(index + 1));

allLatLngs.add(index, centerPoint1);

allLatLngs.add(index + 2, centerPoint2);

Log.e(TAG, "在第" + (index) + "个添加marker");

Log.e(TAG, "在第" + (index + 2) + "个添加marker");

}

}

/**

* 如果拖拽的是状态为1的点,则不需要创建新的点,而是替换两侧的点的坐标(注意是替换set方法)。

*/

private void replaceTwoMarker(Marker marker) {

int index = (int) marker.getObject();

if (index == 0) {

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(0), allLatLngs.get(2));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(0), allLatLngs.get(allLatLngs.size() - 2));

allLatLngs.set(1, centerPoint1);

allLatLngs.set(allLatLngs.size() - 1, centerPoint2);

Log.e(TAG, "替换第" + 1 + "个marker");

Log.e(TAG, "替换第" + (allLatLngs.size() - 1) + "个marker");

return;

}

if (index == allLatLngs.size() - 2) {

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(0), allLatLngs.get(index));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(index), allLatLngs.get(index - 2));

allLatLngs.set(index + 1, centerPoint1);

allLatLngs.set(index - 1, centerPoint2);

Log.e(TAG, "替换第" + (index + 1) + "个marker");

Log.e(TAG, "替换第" + (index - 1) + "个marker");

return;

}

MyLatLng centerPoint1 = getCenterPoint(allLatLngs.get(index - 2), allLatLngs.get(index));

MyLatLng centerPoint2 = getCenterPoint(allLatLngs.get(index + 2), allLatLngs.get(index));

allLatLngs.set(index - 1, centerPoint1);

allLatLngs.set(index + 1, centerPoint2);

Log.e(TAG, "替换第" + (index - 1) + "个marker");

Log.e(TAG, "替换第" + (index + 1) + "个marker");

}

/**

* 获取两个点的中心点坐标

* @param latLng1

* @param latLng2

* @return

*/

private MyLatLng getCenterPoint(MyLatLng latLng1, MyLatLng latLng2) {

BigDecimal bdLL1Lat = new BigDecimal(latLng1.getLatLng().latitude);

BigDecimal bdLL1Lng = new BigDecimal(latLng1.getLatLng().longitude);

BigDecimal bdLL2Lat = new BigDecimal(latLng2.getLatLng().latitude);

BigDecimal bdLL2Lng = new BigDecimal(latLng2.getLatLng().longitude);

BigDecimal d1 = (bdLL1Lat.add(bdLL2Lat)).divide(new BigDecimal("2"));

BigDecimal d2 = (bdLL1Lng.add(bdLL2Lng)).divide(new BigDecimal("2"));

return new MyLatLng(new LatLng(d1.doubleValue(), d2.doubleValue()), MyLatLng.UNABLE);

}

/**

* 绘制图形的颜色样式

*/

private void createAreaStyle() {

int strokeColor = Color.parseColor("#00FFFF");

int fillColor = Color.parseColor("#11000000");

for (MyLatLng myLatLng : allLatLngs) {

polygonOptions.add(myLatLng.getLatLng());

} // 设置多边形的边框颜色,32位 ARGB格式,默认为黑色

polygonOptions.strokeColor(strokeColor); // 设置多边形的边框宽度,单位:像素

polygonOptions.strokeWidth(10); // 设置多边形的填充颜色,32位ARGB格式

polygonOptions.fillColor(fillColor); // 注意要加前两位的透明度 // 在地图上添加一个多边形(polygon)对象

}

/**

* 添加marker

* @param isClear

*/

private void addMarker(boolean isClear) {

if (isClear) {

aMap.clear();

}

for (int i = 0; i < allLatLngs.size(); i++) { // 在地图上添一组图片标记(marker)对象,并设置是否改变地图状态以至于所有的marker对象都在当前地图可视区域范围内显示

MarkerOptions options = new MarkerOptions();

options.position(allLatLngs.get(i).getLatLng()).draggable(true).visible(true);

Marker marker = aMap.addMarker(options);

marker.setObject(i);

if (allLatLngs.get(i).getState() == MyLatLng.ABLE) {

marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.checkbox_fill));

} else {

marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.checkbox_empty));

}

}

}

5.附:自定义MyLatLng

public class MyLatLng {

public static final int ABLE = 1;

public static final int UNABLE = 0;

private LatLng latLng;

private int state;

public MyLatLng(LatLng latLng, int state) {

this.latLng = latLng;

this.state = state;

}

public LatLng getLatLng() {

return latLng;

}

public void setLatLng(LatLng latLng) {

this.latLng = latLng;

}

public int getState() {

return state;

}

public void setState(int state) {

this.state = state;

}

}

升级:

实现效果不是很好,Marker点需要长按才可以使用。所以使用setOnMapTouchListener替代setOnMarkerDragListener。

aMap.setOnMapTouchListener(new AMap.OnMapTouchListener() {

@Override

public void onTouch(MotionEvent motionEvent) {

switch (motionEvent.getAction()) {

case MotionEvent.ACTION_DOWN:

float down_x = motionEvent.getX();

float down_y = motionEvent.getY();

Point downPoint = new Point();

downPoint.set((int) down_x, (int) down_y);

LatLng downLatLng = aMap.getProjection().fromScreenLocation(downPoint);

nearestLatLngIndex = getNearestLatLng(downLatLng);

if (nearestLatLngIndex != -1) {

//说明用户想拖拽该点

//开始拖拽时,把集合里的该点删除掉

allLatLngs.remove(nearestLatLngIndex);

refreshPolygonOptions();

}

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

float up_x = motionEvent.getX();

float up_y = motionEvent.getY();

Point upPoint = new Point();

upPoint.set((int) up_x, (int) up_y);

LatLng upLatLng = aMap.getProjection().fromScreenLocation(upPoint);

//拖拽结束时,创建新点

allLatLngs.add(nearestLatLngIndex, new MyLatLng(upLatLng, MyLatLng.ABLE));

//判断是否需要创建新的点

if (!isCreateMarker(allMarkers.get(nearestLatLngIndex))) {

//不需要

//如果拖拽的是状态为0的点,则不需要创建新的点,而是替换两侧的点的坐标(注意是替换set方法)。

replaceTwoMarker(allMarkers.get(nearestLatLngIndex));

refreshPolygonOptions();

addMarker(true);

createAreaStyle();

aMap.addPolygon(polygonOptions);

} else {

//需要

refreshPolygonOptions();

addMarker(true);

createAreaStyle();

aMap.addPolygon(polygonOptions);

//在拖拽点两侧添加maker

addTwoMarker(allMarkers.get(nearestLatLngIndex));

addMarker(false);

}

break;

}

}

});

/**

* 获取所有点里离该点最近的点的索引值,阈值为2,如果所有值都比2大,则表示没有最近的点(返回-1)

*

* @param latLng

*/

@NonNull

private int getNearestLatLng(LatLng latLng) {

for (int i = 0; i < allLatLngs.size(); i++) {

float distance = AMapUtils.calculateLineDistance(latLng, allLatLngs.get(i).getLatLng());

Log.e(TAG, distance + "");

if (((int) distance) < 2) {

return i;

}

}

return -1;

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。