ClusterManager отображает маркеры Google maps v2 utils
Привет, я делаю запрос сервера, и когда я получил запрос от сервера, я выполняю на 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);
Ответы
Ответ 1
Кажется, я нашел обходное решение.
ClusterManager использует средство визуализации, в этом случае он наследует от DefaultClusterRenderer, который использует внутренний кеш, кеш маркеров, которые добавляются к карте. Вы можете получить доступ к добавленным маркерам на карте, я не использую информационное окно, поэтому я добавляю маркер options.title() идентификатор для последующего поиска этого маркера, поэтому:
@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;
}
}
}
Может быть, немного взломан, но он работает, и я не нашел другого способа сделать это. Если вы нашли другой лучший способ, поделитесь:)
Ответ 2
mClusterManager.cluster();
принудительно повторно кластеризуйте элементы при добавлении нового элемента.
Ответ 3
У меня была та же проблема. Это также усугублялось тем, что я делаю индивидуальный рендеринг в onBeforeClusterItemRendered в моем подклассе DefaultClusterRenderer.
Мое решение состояло в том, чтобы создать новый экземпляр моего подкласса DefaultClusterRenderer и снова вызвать setRenderer в ClusterManager. Это сбрасывает все кэшированные значки и воссоздает все.
Это взломанная, грубая сила и раздражающе неэффективная, но она действительно работает. Это был единственный подход, который я нашел, который работал, поскольку библиотека, похоже, не имеет явной поддержки для этого.
Ответ 4
Вы можете получить определенные маркеры, соответствующие их кластерным или кластерным элементам, и наоборот в O (1), используя DefaultClusterRenderer getMarker(), getCluster() и getClusterItem() (установите собственный рендеринг для доступа к объекту рендеринга).
Используйте эти методы для изменения маркеров ваших элементов, когда вам нужно.
...
DefaultClusterRenderer mRenderer = ...
mClusterManager.setRenderer(mRenderer);
...
public void reloadMarker(ClusterItem item) {
mRenderer.getMarker(item).setIcon(YOUR_ICON);
}
Я бы не рекомендовал сохранять их в другом месте, поскольку эти методы возвращают объекты кэша визуализатора.
Ответ 5
mClusterManager.cluster();
не работал у меня
это произошло, хотя:
if (mMap != null) {
CameraPosition currentCameraPosition = mMap.getCameraPosition();
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(currentCameraPosition));
}
Это вызвало вызов onCameraChange, где я уже выполнял mClusterManager.clearItems()... mClusterManager.addItem(..) - для объектов внутри видимой области... mClusterManager.cluster()
Контекст для меня заключался в том, что контакты исчезали при возврате назад к фрагменту, отображающему карту (- только на определенных устройствах, например Nexus 7, где не было автоматического вызова OnCameraChange)
Ответ 6
У меня была такая же точная проблема. Ни один из предложенных решений не работал у меня. Я создал класс, который расширяет 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());
}
}
Ответ 7
Мое решение с помощью CustomRenderer, расширяющего DefaultClusterRenderer
protected void onClusterItemRendered(T clusterItem, Marker marker) {
marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}