我正在发出服务器请求,当我收到来自服务器的请求时,我正在Ui Thread上执行一个ClusterManager.addItem(),但是这些项目不会在地图中绘制,只有当我进行缩放更新时(+ , - )正在显示。此外,我尝试调试渲染器,但是直到我更新地图中的缩放才调用onBeforeClusterRendered / onBeforeClusterItemRendered。 有关如何刷新map / clusterManager / markers的任何想法吗?
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);
答案 0 :(得分:25)
mClusterManager.cluster();
在添加新项目后强制重新聚类项目。
答案 1 :(得分:15)
似乎我找到了解决方法。
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但是它有效并且我没有找到任何其他方法来做到这一点。如果您找到了另一种更好的方法,请分享:)
答案 2 :(得分:2)
我遇到了同样的问题。我在DefaultClusterRenderer子类上的onBeforeClusterItemRendered中进行自定义渲染也使事情更加复杂。
我的解决方案是创建DefaultClusterRenderer子类的新实例,并再次在ClusterManager上调用setRenderer。这会转储所有缓存的图标&amp;重建一切。
这是hacky,蛮力和恼人的低效率,但确实有效。这是我发现的唯一方法,因为图书馆似乎没有明确的支持。
答案 3 :(得分:2)
您可以使用DefaultClusterRenderer的getMarker(),getCluster()和getClusterItem()(设置您自己的渲染器来访问渲染器对象),在O(1)中获取与其群集或群集项对应的特定标记,反之亦然。 / p>
使用这些方法可以在需要时更改商品的标记。
...
DefaultClusterRenderer mRenderer = ...
mClusterManager.setRenderer(mRenderer);
...
public void reloadMarker(ClusterItem item) {
mRenderer.getMarker(item).setIcon(YOUR_ICON);
}
我不建议将它们保存在其他任何地方,因为这些方法会返回渲染器的缓存对象。
答案 4 :(得分: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)
答案 5 :(得分:2)
我遇到了同样的问题。没有一个建议的解决方案适合我。我创建了一个扩展DefaultClusterRenderer的类,并添加了公共方法updateClusterItem(ClusterItem clusterItem),它将强制重新呈现与该ClusterItem关联的Marker(适用于集群和集群项)。
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());
}
}
答案 6 :(得分:0)
我注意到标记仅在放大或缩小时才会显示,因此我将所有旧值设置为新的相机位置,只是略微改变了变焦。
CameraPosition currentCameraPosition = googleMap.getCameraPosition();
CameraPosition cameraPosition = new CameraPosition(currentCameraPosition.target, currentCameraPosition.zoom - .1f, currentCameraPosition.tilt, currentCameraPosition.bearing);
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
答案 7 :(得分:-1)
我的解决方案使用了一个扩展DefaultClusterRenderer的CustomRenderer
protected void onClusterItemRendered(T clusterItem, Marker marker) {
marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}