【问题标题】:Setting a LongClickListener on a map Marker在地图标记上设置 LongClickListener
【发布时间】:2013-03-13 16:57:39
【问题描述】:

有没有办法在谷歌地图 v2 的标记上设置longClickListsner?我想让用户长按标记并显示一个对话框,其中包含删除或查看信息的选项。这个可以吗?

【问题讨论】:

    标签: android google-maps google-maps-android-api-2


    【解决方案1】:

    我还有一个提议。

    首先我使标记可拖动:

    mapa.addMarker(new MarkerOptions()  ...     
          .setDraggable(true);
    

    之后你可以像这样设置监听器 setOnMarkerDragListener:

    mapa.setOnMarkerDragListener(new OnMarkerDragListener() {
    
                @Override
                public void onMarkerDragStart(Marker marker) {
                    // TODO Auto-generated method stub
                    //Here your code
                }
    
                @Override
                public void onMarkerDragEnd(Marker marker) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void onMarkerDrag(Marker marker) {
                    // TODO Auto-generated method stub
    
                }
            });
    

    然后你可以覆盖你想要的(通常是 onMarkerDragStart 来模拟长按)

    希望对你有帮助

    【讨论】:

    • 我已经尝试过了,但我的标记只需点击即可更改位置。我还没有开始拖动它,只是点击它,它就改变了。我不想这样做。你能建议我任何其他方式吗?
    • 我认为是因为标记位于您触摸的点的中心。不知道有没有办法解决,抱歉。
    【解决方案2】:

    Marker 类没有 LongClickListener。虽然这种方法远非完美,但这里有一个关于您可以做什么的想法。

    为您的 GoogleMap 对象设置长点击侦听器。长按时,检查单击的位置是否足够靠近您的任何标记。要确定此接近度阈值,您可以使用地图缩放级别。

    这里是不太好的示例代码。我还没有尝试过,但它可能适合您的需求。

        map.setOnMapLongClickListener(new OnMapLongClickListener() {
    
                @Override
                public void onMapLongClick(LatLng latLng) {
                    for(Marker marker : yourMarkerList) {
                        if(Math.abs(marker.getPosition().latitude - latLng.latitude) < 0.05 && Math.abs(marker.getPosition().longitude - latLng.longitude) < 0.05) {
                            Toast.makeText(MapActivity.this, "got clicked", Toast.LENGTH_SHORT).show(); //do some stuff
                            break;
                        }
                    }
    
                }
            });
    

    【讨论】:

    • 这是一种方法,但它不是万无一失的,因为你可以选择一个你不想要的标记,直到你删除它才会知道
    • @tyczj 是的,它不是防犯规的。尽管如此,即使标记有一个监听器,当它们太靠近时也会发生误点击。 Imo,检查最接近的标记不会带来额外的问题。无论如何都会发生误点击,您只需让用户确认操作即可。
    • 由于手指粗细和地图缩放,附近的大量点似乎无法正常工作
    • 区别应该在“屏幕像素”而不是纬度..
    【解决方案3】:

    按照 ARP 的建议,您可以使用 OnMarkerDragListener 来模拟长按。就我而言,当 onMapLongClick() 发生时,我正在创建新标记,所以我想做一些与

    类似(但不相等)的事情
    @Override
    public void onMarkerDragStart(Marker marker) {
        marker.remove();
        MarkerOptions options = createBasedOnMarker(marker);
        this.googleMap.addMarker(options);
    }
    

    这样,您将删除之前在地图中的标记,并在相同位置创建另一个具有相同内容的标记(您必须拥有地图或配对以保留您创建的标记中的信息)。

    希望我的解决方法有所帮助。

    【讨论】:

      【解决方案4】:

      ARP 的答案很好,但它有一个丑陋的效果:当你开始拖动时,标记会向上移动,而当你完成时,标记仍处于比你用手指指向更高的位置。

      看看http://www.youtube.com/watch?v=RxAHHJD4nU8

      【讨论】:

        【解决方案5】:

        akaya's answer 不是一个坏方法,但如果你的项目有 com.google.maps.android:android-maps-utils:0.3+ library included 你可以确切的距离:

        double distance = SphericalUtil.computeDistanceBetween( 
            marker.getPosition(), 
            latLng 
        );
        if( distance < 50 ) { // closer than 50 meters?
            //..do stuff..
        }
        

        【讨论】:

        【解决方案6】:

        嘿,看看这段代码,我刚刚阻止了标记被拖动并使用了onMarkerDragStart 的长按检测。

        public abstract class LinkMarkerLongClickListener implements GoogleMap.OnMarkerDragListener {
        
            private int previousIndex = -1;
        
            private Marker cachedMarker = null;
            private LatLng cachedDefaultPostion = null;
        
            private List<Marker> markerList;
            private List<LatLng> defaultPostions;
        
            public LinkMarkerLongClickListener(List<Marker> markerList){
                this.markerList = new ArrayList<>(markerList);
                defaultPostions = new ArrayList<>(markerList.size());
                for (Marker marker : markerList) {
                    defaultPostions.add(marker.getPosition());
                    marker.setDraggable(true);
                }
            }
        
            public abstract void onLongClickListener(Marker marker);
        
            @Override
            public void onMarkerDragStart(Marker marker) {
                onLongClickListener(marker);
                setDefaultPostion(markerList.indexOf(marker));
            }
        
            @Override
            public void onMarkerDrag(Marker marker) {
                setDefaultPostion(markerList.indexOf(marker));
            }
        
            @Override
            public void onMarkerDragEnd(Marker marker) {
                setDefaultPostion(markerList.indexOf(marker));
            }
        
        
            private void setDefaultPostion(int markerIndex) {
                if(previousIndex == -1 || previousIndex != markerIndex){
                    cachedMarker = markerList.get(markerIndex);
                    cachedDefaultPostion = defaultPostions.get(markerIndex);
                    previousIndex = markerIndex;
                }
                cachedMarker.setPosition(cachedDefaultPostion);
            }
        }
        

        你可以这样调用监听器!

        map.setOnMarkerDragListener(new LinkMarkerLongClickListener(markers) {
                    @Override
                    public void onLongClickListener(Marker marker) {
                        ToastUtils.showToast(Mission1Activity.this, marker.getTitle());
                    }
                });
        

        【讨论】:

        • 当我这样做时,我的用户似乎仍然能够在屏幕上拖动标记。有解决办法吗?
        【解决方案7】:

        以防万一有人需要它,我调整了一个对数函数来计算@akaya 提到的接近度阈值,它适用于 5.0 到 18 之间的缩放。这是函数:

        float zoom = mMap.getCameraPosition().zoom;
        double maxDistance = 2000000 * Math.exp(-0.644*zoom);
        

        【讨论】:

          【解决方案8】:

          这是一个简单的工作解决方案。我们需要使用屏幕 xy 来检查距离。

          googleMap.setOnMapLongClickListener{ loc ->
                          var distance = 10000
                          var nearestMarker: Marker? = null
                          allBcmMarkers.forEach { mrkr ->
                              googleMap?.projection?.let { prj ->
                                  val tapXY = prj.toScreenLocation(loc)
                                  val mrkrXY = prj.toScreenLocation(mrkr.position)
                                  val THRESH = 50
                                  val xDiff = abs(tapXY.x - mrkrXY.x)
                                  val yDiff = abs(tapXY.y - mrkrXY.y)
                                  if (xDiff < THRESH && yDiff < THRESH) {
                                      val mrkrDist =
                                          sqrt((xDiff * xDiff + yDiff * yDiff + xDiff * yDiff).toDouble())
                                      if (mrkrDist < distance) {
                                          distance = mrkrDist.toInt()
                                          nearestMarker = mrkr
                                      }
                                  }
                              }
                          }
          
                          // you have nearestMarker
                  }
              }
          

          【讨论】:

            猜你喜欢
            • 2019-03-07
            • 1970-01-01
            • 2014-05-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-27
            • 1970-01-01
            相关资源
            最近更新 更多