最近项目中用到了一个高德地图画地块的功能,差了一下api,发现只有js有相关的方法,所以仿照js的交互方式做了一个android版的多边形绘制与编辑。
先不说,上一张效果图
完成效果图
1.通过观察,我们大致能知道主要的绘制与编辑方式,点完第二个点之后,和第一个点连成线段,这个线段的中间位置会有一个小点,下面是添加marker点的代码
/**
* 添加marker
*/
private void addMarker(LatLng latLng) {
if (allLatLngs.size() == 0) {
MarkerOptions options= new MarkerOptions();
options.position(latLng).draggable(false).visible(true);
Marker marker= aMap.addMarker(options);
marker.setObject((allLatLngs.size() + 1));
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_dian_s));
marker.setAnchor(0.5f, 0.5f);
allLatLngs.add(new MyLatLng(latLng, MyLatLng.ABLE));
allLatLngsWithLine.add(latLng);
markers.add(marker);
//画线
drawLine(latLng, null);
} else {
if (isEnd) {
MarkerOptions options= new MarkerOptions();
latLng= new LatLng(((latLng.latitude + allLatLngs.get(allLatLngs.size() - 1).getLatLng().latitude) / 2), ((latLng.longitude + allLatLngs.get(allLatLngs.size() - 1).getLatLng().longitude) / 2));
options.position(latLng).draggable(false).visible(true);
Marker marker= aMap.addMarker(options);
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_dian_y));
marker.setAnchor(0.5f, 0.5f);
allLatLngs.add(new MyLatLng(latLng, MyLatLng.UNABLE));
allLatLngsWithLine.add(latLng);
markers.add(marker);
drawLine(allLatLngsWithLine.get(allLatLngsWithLine.size() - 1), allLatLngsWithLine.get(0));
} else {
for (int i= 0; i< 2; i++) { // 在地图上添一组图片标记(marker)对象,并设置是否改变地图状态以至于所有的marker对象都在当前地图可视区域范围内显示
MarkerOptions options= new MarkerOptions();
if (i== 0) {
LatLng latLng2= new LatLng(((latLng.latitude + allLatLngs.get(allLatLngs.size() - 1).getLatLng().latitude) / 2), ((latLng.longitude + allLatLngs.get(allLatLngs.size() - 1).getLatLng().longitude) / 2));
options.position(latLng2).draggable(false).visible(true);
allLatLngs.add(new MyLatLng(latLng2, MyLatLng.UNABLE));
allLatLngsWithLine.add(latLng2);
} else {
options.position(latLng).draggable(false).visible(true);
allLatLngs.add(new MyLatLng(latLng, MyLatLng.ABLE));
allLatLngsWithLine.add(latLng);
}
Marker marker= aMap.addMarker(options);
marker.setAnchor(0.5f, 0.5f);
if (i== 1) {
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_dian_s));
} else {
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_dian_y));
}
markers.add(marker);
}
drawLine(allLatLngsWithLine.get(allLatLngsWithLine.size() - 2), allLatLngsWithLine.get(allLatLngsWithLine.size() - 1));
}
}
}
2.画上marker点之后还要画点之间的线,还有多边形的填充色这里贴一下相关的代码
/**
* 画线
*/
private void drawLine(LatLng latLng, LatLng latLng2) {
if (polyline == null) {
polyline = aMap.addPolyline(new PolylineOptions().
add(latLng).width(10).color(Color.argb(255, 1, 1, 1)));
} else {
List points= polyline.getPoints();
if (isEnd) {
points.add(latLng);
points.add(latLng2);
} else {
if (!points.contains(latLng)) {
points.add(latLng);
}
if (!points.contains(latLng2)) {
points.add(latLng2);
}
}
polyline.setPoints(points);
//计算周长
setPerimeter();
}
}
/**
* 画多边形
*/
private void drawRect() {
if (polygon == null) {
polygonOptions.addAll(allLatLngsWithLine);
//创建多边形
polygon = aMap.addPolygon(polygonOptions);
} else {
polygon.setPoints(allLatLngsWithLine);
}
//计算面积
setArea();
}
3.是时候该拖动marker点改变多边形的形状了.一开始我是准备用marker点的监听做它的移动监听的,发现marker的拖动必须要长按才能拖动,用户体验并不好,所以就改成了地图的触摸监听.大致说一下思路:如果拖拽的是大点,则改变其左右两个小点的坐标和与其相邻的两个大点间的线段,而拖拽小点则先将其变成一个大点,然后在与其相邻的两个大点之间添加两个小点就行.下面上关键代码
//添加拖拽事件
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);
//获取触摸的点下标
checkPos = getNearestLatLng(downLatLng);
//触摸的点是矩形的点
if (checkPos > -1) {
//如果是小点
if (allLatLngs.get(checkPos).getState() == MyLatLng.UNABLE) {
//更改为大点
chageMarker();
//如果是封闭图形并且点击的是最后的一个点
if (isEnd && checkPos == allLatLngs.size() - 1) {
//添加两个mark
addTwoMarker(getCenterLatlng(allLatLngs.get(checkPos).getLatLng(), allLatLngs.get(checkPos - 1).getLatLng()), getCenterLatlng(allLatLngs.get(checkPos).getLatLng(), allLatLngs.get(0).getLatLng()));
} else {
//不是封闭图形
//添加两个marker
addTwoMarker(getCenterLatlng(allLatLngs.get(checkPos).getLatLng(), allLatLngs.get(checkPos - 1).getLatLng()), getCenterLatlng(allLatLngs.get(checkPos).getLatLng(), allLatLngs.get(checkPos + 1).getLatLng()));
}
//将选中点的下标更改
checkPos += 1;
}
//获取选中的marker点
touchMark = markers.get(checkPos);
//禁止地图放大旋转等操作