21

我正在发出服务器请求,当我收到来自服务器的响应时,我正在 UI 线程 a 上执行,ClusterManager.addItem()但这些项目没有在地图中绘制,只有当我进行缩放更新 (+,-) 时才开始新添加的项目出现。我也尝试调试渲染器,但在我更新放大地图之前不会调用onBeforeClusterRendered/ 。onBeforeClusterItemRendered

任何想法如何刷新地图/集群管理器/标记?

MarkerManager markerManager = new MarkerManager(map);
clusterManager = new ClusterManager<TweetClusterItem>(getActivity(), map, markerManager);
clusterManager.setRenderer(new TweetClusterRenderer(getActivity(), map, clusterManager, defaultMarker));
clusterManager.setOnClusterClickListener(this);
clusterManager.setOnClusterInfoWindowClickListener(this);
clusterManager.setOnClusterItemClickListener(this);
clusterManager.setOnClusterItemInfoWindowClickListener(this);

UiSettings uiSettings = map.getUiSettings();
uiSettings.setZoomControlsEnabled(true);
uiSettings.setMyLocationButtonEnabled(false);

map.setOnCameraChangeListener(clusterManager);
map.setOnMarkerClickListener(clusterManager);
map.setOnInfoWindowClickListener(clusterManager);
map.setOnMapClickListener(this);
4

8 回答 8

26

mClusterManager.cluster();

添加新项目后强制重新聚类项目。

于 2014-03-14T02:52:10.983 回答
17

似乎我找到了解决方法。

ClusterManager 使用渲染器,在这种情况下,它继承自 DefaultClusterRenderer,后者使用内部缓存,即添加到地图的标记缓存。您可以直接访问地图上添加的标记,我不使用信息窗口,所以我添加标记 options.title() 一个 ID 以便以后找到这个标记,所以:

@Override
protected void onBeforeClusterItemRendered(TweetClusterItem item, MarkerOptions markerOptions) {

     .... Blabla code....          
            markerOptions.title(Long.toString(tweet.getId()));
     .... Blabla code....


}

当我想重新加载 clusterItem 时,我调用这个方法:

/**
  * Workarround to repaint markers
  * @param item item to repaint
 */
  public void reloadMarker(TweetClusterItem item) {

        MarkerManager.Collection markerCollection = clusterManager.getMarkerCollection();
        Collection<Marker> markers = markerCollection.getMarkers();
        String strId = Long.toString(item.getTweet().getId());
        for (Marker m : markers) {
            if (strId.equals(m.getTitle())) {
                m.setIcon( ICON TO SET);
                break;
            }
        }

    }

也许有点hacky,但它有效,我没有找到任何其他方法来做到这一点。如果您发现了另一种更好的方法,请分享:)

于 2014-03-10T10:04:10.720 回答
3

您可以使用 DefaultClusterRenderer 的 getMarker()、getCluster() 和 getClusterItem()(设置您自己的渲染器以访问渲染器对象)在 O(1) 中获取与其集群或集群项目相对应的特定标记,反之亦然。

随时使用这些方法更改项目的标记。

   ...
   DefaultClusterRenderer mRenderer = ...
   mClusterManager.setRenderer(mRenderer);
   ...

public void reloadMarker(ClusterItem item) {
    mRenderer.getMarker(item).setIcon(YOUR_ICON);
}

不过,我不建议将它们保存在其他任何地方,因为这些方法会返回渲染器的缓存对象。

于 2015-08-12T19:08:03.053 回答
3

我遇到了同样的问题。没有一个建议的解决方案对我有用。我创建了一个扩展 DefaultClusterRenderer 的类,并添加了公共方法 updateClusterItem(ClusterItem clusterItem),这将强制重新渲染与该 ClusterItem 关联的标记(适用于集群和集群项)。

import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterItem;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


public abstract class CustomClusterRenderer<T extends ClusterItem>
        extends DefaultClusterRenderer<T> {

    private ClusterManager<T> mClusterManager;
    private Map<T, Marker> mClusterMap = new HashMap<>();

    public CustomClusterRenderer(Context context, GoogleMap map,
                                 ClusterManager<T> clusterManager) {
        super(context, map, clusterManager);
        mClusterManager = clusterManager;
    }


    @Override
    @CallSuper
    protected void onClusterItemRendered(T clusterItem, Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
        mClusterMap.remove(clusterItem);
        cleanCache();
    }

    @Override
    @CallSuper
    protected void onClusterRendered(Cluster<T> cluster, Marker marker) {
        super.onClusterRendered(cluster, marker);
        for (T clusterItem : cluster.getItems()) {
            mClusterMap.put(clusterItem, marker);
        }
        cleanCache();
    }

    public void updateClusterItem(T clusterItem) {
        Marker marker = getMarker(clusterItem);
        boolean isCluster = false;
        if (marker == null) {
            marker = mClusterMap.get(clusterItem);
            isCluster = marker != null;
        }
        if (marker != null) {
            MarkerOptions options = getMarkerOptionsFromMarker(marker);
            if (isCluster) {
                Cluster cluster = getCluster(marker);
                onBeforeClusterRendered(cluster, options);
            } else {
                onBeforeClusterItemRendered(clusterItem, options);
            }
            loadMarkerWithMarkerOptions(marker, options);
        }
    }

    private void cleanCache() {
        ArrayList<T> deleteQueue = new ArrayList<>();
        Collection<Marker> clusterMarkers = mClusterManager
                .getClusterMarkerCollection().getMarkers();

        for (T clusterItem : mClusterMap.keySet()) {
            if (!clusterMarkers.contains(mClusterMap.get(clusterItem))) {
                deleteQueue.add(clusterItem);
            }
        }

        for (T clusterItem : deleteQueue) {
            mClusterMap.remove(clusterItem);
        }
        deleteQueue.clear();
    }

    private MarkerOptions getMarkerOptionsFromMarker(@NonNull Marker marker) {
        MarkerOptions options = new MarkerOptions();

        options.alpha(marker.getAlpha());
        options.draggable(marker.isDraggable());
        options.flat(marker.isFlat());
        options.position(marker.getPosition());
        options.rotation(marker.getRotation());
        options.title(marker.getTitle());
        options.snippet(marker.getSnippet());
        options.visible(marker.isVisible());
        options.zIndex(marker.getZIndex());

        return options;
    }

    private void loadMarkerWithMarkerOptions(@NonNull Marker marker,
                                             @NonNull MarkerOptions options) {
        marker.setAlpha(options.getAlpha());
        marker.setDraggable(options.isDraggable());
        marker.setFlat(options.isFlat());
        marker.setPosition(options.getPosition());
        marker.setRotation(options.getRotation());
        marker.setTitle(options.getTitle());
        marker.setSnippet(options.getSnippet());
        marker.setVisible(options.isVisible());
        marker.setZIndex(options.getZIndex());
        marker.setIcon(options.getIcon());
        marker.setAnchor(options.getAnchorU(), options.getAnchorV());
        marker.setInfoWindowAnchor(options.getInfoWindowAnchorU(), options.getInfoWindowAnchorV());
    }

}
于 2016-08-17T21:50:33.307 回答
2

我有同样的问题。我在我的 DefaultClusterRenderer 子类的 onBeforeClusterItemRendered 中进行自定义渲染的事实也使情况更加复杂。

我的解决方案是创建我的 DefaultClusterRenderer 子类的新实例并再次在 ClusterManager 上调用 setRenderer。这会转储所有缓存的图标并重新创建所有内容。

这是 hacky,蛮力和令人讨厌的低效,但它确实有效。这是我发现的唯一可行的方法,因为该库似乎对此没有明确的支持。

于 2014-09-17T16:31:47.287 回答
2

mClusterManager.cluster(); 对我不起作用

但这确实:

if (mMap != null) {
    CameraPosition currentCameraPosition = mMap.getCameraPosition();
    mMap.moveCamera(CameraUpdateFactory.newCameraPosition(currentCameraPosition));
}

这触发了 onCameraChange 调用,我已经在其中执行 mClusterManager.clearItems()... mClusterManager.addItem(..) - 对于可见区域内的对象... mClusterManager.cluster()

我的上下文是,当返回显示地图的片段时,图钉消失了(仅在某些设备上,例如 Nexus 7,没有自动调用 OnCameraChange)

于 2015-11-03T18:37:45.787 回答
0

我注意到标记仅在放大或缩小时出现,所以我用所有旧值设置了一个新的相机位置,除了轻微的缩放变化。

    CameraPosition currentCameraPosition = googleMap.getCameraPosition();
    CameraPosition cameraPosition = new CameraPosition(currentCameraPosition.target, currentCameraPosition.zoom - .1f, currentCameraPosition.tilt, currentCameraPosition.bearing);
    googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
于 2020-02-08T22:38:05.253 回答
-2

我使用扩展 DefaultClusterRenderer 的 CustomRenderer 的解决方案

 protected void onClusterItemRendered(T clusterItem, Marker marker) {
    marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
于 2015-10-18T21:25:25.127 回答