Android谷歌地图添加GeoJson图层后如何同时触发双端点击事件
解决GeoJson Polygon点击与地图点击同时响应的问题
我之前也碰到过类似的需求,官方文档里明确说点击事件只会触发最高z-index的对象,没法让系统自动传递事件。不过我们可以通过两种靠谱的方式实现同时响应:
方法一:在Feature点击监听器中手动复用地图点击逻辑
虽然OnFeatureClickListener的回调没有直接提供点击位置,但我们可以换个思路:先通过OnMapClickListener记录所有地图点击的位置,当Feature被点击时,直接复用最近一次记录的位置信息,同时执行地图点击的处理逻辑。
示例代码:
// 定义变量存储最新的地图点击位置 private LatLng lastMapClickPos; // 先设置地图点击监听器,记录所有点击位置 map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { lastMapClickPos = latLng; // 这里处理非Polygon区域的地图点击逻辑 Log.i("MapClick", "点击位置经纬度:" + latLng.latitude + ", " + latLng.longitude); } }); // 设置GeoJson图层的Feature点击监听器 layer.setOnFeatureClickListener(new GeoJsonLayer.OnFeatureClickListener() { @Override public void onFeatureClick(Feature feature) { // 先处理Polygon Feature的点击逻辑 Log.i("GeoJsonClick", "点击的Feature:" + feature.getProperty("AName")); // 手动触发地图点击的逻辑,复用之前记录的位置 if (lastMapClickPos != null) { Log.i("MapClick", "从Feature点击触发的位置:" + lastMapClickPos.latitude + ", " + lastMapClickPos.longitude); // 这里可以直接调用地图点击的处理方法,或者复制逻辑过来 } } });
注意:如果点击的是Polygon区域,OnMapClickListener本身不会被触发,但我们提前记录了所有点击位置,所以Feature点击时仍能拿到对应的经纬度。
方法二:放弃Feature点击监听器,在地图点击中手动判断点是否在Polygon内
这种方式更灵活可控,我们直接在OnMapClickListener中获取点击位置,然后遍历GeoJson图层里的所有Polygon,判断点击点是否落在某个Polygon中,这样既能拿到经纬度,又能处理Feature的点击逻辑。
首先需要一个判断点是否在多边形内的工具方法(用射线法实现):
// 射线法判断点是否在Polygon内 private boolean isPointInPolygon(LatLng point, List<LatLng> polygonPoints) { int vertexCount = polygonPoints.size(); boolean isInside = false; for (int i = 0, j = vertexCount - 1; i < vertexCount; j = i++) { LatLng pI = polygonPoints.get(i); LatLng pJ = polygonPoints.get(j); if (((pI.latitude > point.latitude) != (pJ.latitude > point.latitude)) && (point.longitude < (pJ.longitude - pI.longitude) * (point.latitude - pI.latitude) / (pJ.latitude - pI.latitude) + pI.longitude)) { isInside = !isInside; } } return isInside; }
然后在地图点击监听器中处理逻辑:
// 先获取GeoJson图层里的所有Polygon Feature List<Feature> polygonFeatures = layer.getFeatures(); // 设置地图点击监听器 map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { // 第一步:处理地图点击逻辑,拿到经纬度 Log.i("MapClick", "点击位置经纬度:" + latLng.latitude + ", " + latLng.longitude); // 第二步:遍历所有Polygon,判断点击点是否在其中 for (Feature feature : polygonFeatures) { if (feature.getGeometry() instanceof Polygon) { Polygon polygon = (Polygon) feature.getGeometry(); List<LatLng> polygonPoints = polygon.getCoordinates(); if (isPointInPolygon(latLng, polygonPoints)) { // 处理Feature的点击逻辑 Log.i("GeoJsonClick", "点击的Feature:" + feature.getProperty("AName")); // 如果只需要响应第一个命中的Polygon,直接break即可 break; } } } } });
这种方式的优势是完全由我们控制事件流程,不受z-index限制,而且能灵活处理多个重叠Polygon的点击判断。如果你的GeoJson包含带洞的嵌套Polygon,只需要稍微调整射线法的逻辑即可适配。
内容的提问来源于stack exchange,提问作者Zaid Mirza
相关产品推荐
相关产品推荐

