基于Google Maps dragListener实现可编辑多多边形的问题求助
我来帮你解决这个问题!你遇到的崩溃和编辑失效问题,核心原因是你只用了单个变量来存储当前多边形的点、标记和多边形对象,当你新建第二个多边形时,旧多边形的标记和点就和当前的points、markerList脱节了——拖动旧标记时,代码会去当前的points里找对应的位置,自然找不到(返回-1),调用points.set(position, ...)就会抛出索引越界异常。
解决方案:封装多边形数据,维护多边形列表
我们需要为每个多边形创建独立的数据集,确保每个标记都能关联到自己所属的多边形。具体实现步骤如下:
1. 定义多边形数据类
创建一个类来封装单个多边形的所有关联信息:
public class PolygonData { public List<LatLng> points; public List<Marker> markers; public Polygon polygon; public PolygonData() { points = new ArrayList<>(); markers = new ArrayList<>(); } }
2. 替换全局变量为多边形列表
在你的Activity中,替换原来的单个变量为多边形列表和当前绘制的多边形:
private GoogleMap mMap; private List<PolygonData> polygonList = new ArrayList<>(); private PolygonData currentPolygon; // 当前正在绘制的多边形
3. 修改地图初始化与点击逻辑
更新onMapReady方法,确保每次点击地图时,标记和点都关联到当前多边形:
@Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; // 保留原有的地图初始化代码(相机位置、缩放等) CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(40.76793169992044, -73.98180484771729)); CameraUpdate zoom = CameraUpdateFactory.zoomTo(15); mMap.moveCamera(center); mMap.animateCamera(zoom); mMap.setIndoorEnabled(false); // 初始化第一个多边形 newPolygon(null); mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { Marker marker = mMap.addMarker(new MarkerOptions().position(latLng).draggable(true)); // 将当前多边形关联到标记,拖动时能找到所属多边形 marker.setTag(currentPolygon); currentPolygon.markers.add(marker); currentPolygon.points.add(latLng); drawCurrentPolygon(); } }); mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() { @Override public void onMarkerDragStart(Marker marker) {} @Override public void onMarkerDrag(Marker marker) { updateMarkerPosition(marker, false); } @Override public void onMarkerDragEnd(Marker marker) { updateMarkerPosition(marker, true); } }); }
4. 更新新建多边形方法
每次点击新建按钮时,创建一个新的多边形实例并加入列表:
public void newPolygon(View view) { currentPolygon = new PolygonData(); polygonList.add(currentPolygon); }
5. 修复标记拖动更新逻辑
现在通过标记的Tag找到对应的多边形,再更新该多边形的点和图形:
private void updateMarkerPosition(Marker marker, boolean redraw) { PolygonData polygonData = (PolygonData) marker.getTag(); if (polygonData == null) return; // 找到标记在当前多边形中的索引 int markerIndex = polygonData.markers.indexOf(marker); if (markerIndex == -1) return; // 更新对应的点位置 polygonData.points.set(markerIndex, marker.getPosition()); if (redraw) { drawPolygon(polygonData); } }
6. 重写多边形绘制方法
针对单个PolygonData绘制,确保每个多边形独立更新:
private void drawCurrentPolygon() { drawPolygon(currentPolygon); } private void drawPolygon(PolygonData polygonData) { // 移除旧的多边形实例 if (polygonData.polygon != null) { polygonData.polygon.remove(); } // 至少3个点才能绘制多边形 if (polygonData.points.size() >= 3) { PolygonOptions polygonOptions = new PolygonOptions() .addAll(polygonData.points) .strokeColor(Color.BLUE) .fillColor(Color.argb(50, 0, 0, 255)); polygonData.polygon = mMap.addPolygon(polygonOptions); } else { polygonData.polygon = null; } }
7. 可选:完善闭合多边形功能
你可以在closePolygon方法中添加自动闭合逻辑:
public void closePolygon(View view) { if (currentPolygon != null && currentPolygon.points.size() >= 3) { // 闭合多边形(将第一个点添加到列表末尾) currentPolygon.points.add(currentPolygon.points.get(0)); drawPolygon(currentPolygon); // 可选:闭合后自动新建一个多边形 // newPolygon(null); } }
关键改进点说明
- 每个多边形的点、标记、图形对象都封装在
PolygonData中,不同多边形之间不会互相干扰 - 标记通过
Tag关联到所属多边形,拖动时能精准定位到对应的数据集 - 维护了所有多边形的列表,方便后续的批量编辑、保存等扩展操作
内容的提问来源于stack exchange,提问作者Arpit Patel
相关产品推荐
相关产品推荐

