移动标记时谷歌地图显示两个标记

Posted

技术标签:

【中文标题】移动标记时谷歌地图显示两个标记【英文标题】:Google Maps Displays two Markers when Marker Moved 【发布时间】:2020-07-02 00:22:49 【问题描述】:

我正在使用 Google Maps android SDK 使用标记填充地图,这些标记的位置存储在我的应用程序的所有用户通用的 Firebase 数据库中。每个标记的数据都存储在唯一的 Firebase 记录中,每条记录都包含标记的纬度和经度以及一个布尔值,指示该位置是否已经过验证。 标记最初通过 childAdded 侦听器添加到 Map。然后,该应用“侦听” Firebase 数据库中的以下事件:

添加了一个新标记 现有标记已更改(移动到新位置和/或“已验证”) 现有标记被删除

我已经实现了一个哈希映射,如How to update marker positions with data from Firebase Google Maps API Android 所示。

添加标记时,会将条目添加到哈希映射中,其中 Firebase pushID(键)用作哈希映射中标记对象的索引(请参见下面的代码)。

    private Map<String, Marker> mMarkerMap = new HashMap<> ();
        DatabaseReference dbRef = FirebaseDatabase.getInstance ().getReference ();
        DatabaseReference markerRef = dbRef.child ( "markers" );
        //load all markers when app starts
        //child added returns all markers, then listens for new additions
        //Log.i(TAG, "Database Reference: " + dbRef);
        //List<SymbolOptions> options = new ArrayList<> ();
        markerRef.addChildEventListener ( new ChildEventListener () 
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) 
                try 
                    markerKey = dataSnapshot.getKey ();
                    Log.i ( TAG, "Adding Markers: " );
                    Log.i ( TAG, "Marker Key: " + markerKey );
                    double x = (Double) dataSnapshot.child ( "x" ).getValue ();
                    double y = (Double) dataSnapshot.child ( "y" ).getValue ();
                    boolean v = (Boolean) dataSnapshot.child ( "v" ).getValue ();
                    Log.i ( TAG, "Marker Data - x: " + x + " y: " + y + " v: " + v );
                    if (v == true) 
                        Marker marker = mMap.addMarker ( new MarkerOptions ()
                                .position ( new LatLng ( y, x ) )
                                .icon ( BitmapDescriptorFactory.fromResource ( R.drawable.verified ) ) );
                        marker.setTag(markerKey);
                        mMarkerMap.put (markerKey, marker);
                     else 
                        Marker marker = mMap.addMarker ( new MarkerOptions ()
                                .position ( new LatLng ( y, x ) )
                                .icon ( BitmapDescriptorFactory.fromResource ( R.drawable.unverified ) ) );
                        marker.setTag(markerKey);
                        mMarkerMap.put (markerKey, marker);
                    
                 catch (Error error) 
                    noFirebaseAccessAlert ();
                
            

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) 
                try 
                    markerKey = dataSnapshot.getKey ();
                    Log.i ( TAG, "Changing Marker: " );
                    Log.i ( TAG, "Marker Key: " + markerKey );
                    double x = (Double) dataSnapshot.child ( "x" ).getValue ();
                    double y = (Double) dataSnapshot.child ( "y" ).getValue ();
                    boolean v = (Boolean) dataSnapshot.child ( "v" ).getValue ();
                    Log.i ( TAG, "Marker Data - x: " + x + " y: " + y + " v: " + v );
                    Marker changedMarker = mMarkerMap.get(markerKey);
                    if (v == true) 
                        changedMarker.setPosition (new LatLng(y,x));
                        changedMarker.setIcon ( BitmapDescriptorFactory.fromResource ( R.drawable.verified ) );
                     else 
                        changedMarker.setPosition (new LatLng(y,x));
                        changedMarker.setIcon ( BitmapDescriptorFactory.fromResource ( R.drawable.unverified ) );
                    
                 catch (Error error) 
                    noFirebaseAccessAlert ();
                
            

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) 
                try 
                    markerKey = dataSnapshot.getKey ();
                    Log.i ( TAG, "Deleting Marker: " );
                    Log.i ( TAG, "Marker Key: " + markerKey );
                    Marker deletedMarker = mMarkerMap.get (markerKey);
                    deletedMarker.remove ();
                    mMarkerMap.remove(markerKey);
                 catch (Error error) 
                    noFirebaseAccessAlert ();
                
            

问题在于,当 Firebase 中的数据发生更改并调用“childChanged”侦听器时,会在地图上的更新位置放置一个新图标,但保留原始图标。 哈希表中没有新条目。

如果我点击任一图标,“onClickMarker”函数会收到相同的标记标识符。 我可以简单地删除现有标记并添加一个新标记,但如果可能,我宁愿移动现有标记。

这是一个已知问题吗?

【问题讨论】:

发现问题。不是谷歌地图问题。另一个例程是两次调用上面的代码,因此在彼此之上添加了两个标记。当我移动一个时,另一个仍然存在。上面的代码工作正常。 更新了添加“标签”的代码,以便“onClickMarker”可以识别被点击的正确标记。 以上代码已经过测试,可以正常运行。 【参考方案1】:

在您的代码中,问题在这里

Marker marker = mMap.addMarker ( new MarkerOptions ()
                                .position ( new LatLng ( y, x ) )
                                .icon ( BitmapDescriptorFactory.fromResource ( R.drawable.verified ) ) );

你每次都创建新的 Marker 对象,不需要每次都创建新的 Marker 对象,你只需在创建对象后设置你的标记位置。就像下面的代码..

Marker marker;

            if (mMap != null) 
                if (marker == null) 
                    MarkerOptions options = new MarkerOptions().position(mLatlng)
                            .title(mCity);
                    marker = mMap.addMarker(options);
                 else 
                    marker.setPosition(mLatlng);
                
                mMap.moveCamera(CameraUpdateFactory.newLatLng(mLatlng));
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mLatlng, 15f));
            

【讨论】:

谢谢 - 如果您指的是在“childAdded”侦听器中添加标记,它是在最初调用侦听器时将 Firebase 中的所有现有标记添加到地图中,然后侦听任何添加被制作到数据库中。如果“childChanged”侦听器检测到该特定标记的 Firebase 数据发生变化,则它会修改现有标记,并使用哈希映射获取标记对象。如果“childRemoved”侦听器检测到标记已被删除,则它会从映射和哈希映射中删除特定标记。同意??

以上是关于移动标记时谷歌地图显示两个标记的主要内容,如果未能解决你的问题,请参考以下文章

如何使用相机谷歌地图 xcode 移动标记(图钉)

再次单击时谷歌地图标记发生变化 - Fidde 附加

谷歌地图:如何防止 InfoWindow 移动地图

移动地图时,在谷歌地图中更新Ajax Json数组中的标记

从 web api 加载谷歌地图所需的标记,并在相机移动时动态加载其他标记

移动谷歌地图标记点时用纬度和经度更新数据库