ClusterManager Repaint marqueurs de Google maps v2 utils

Salut Im faisant une requête de serveur et quand j'ai reçu la requête de serveur, j'exécute sur Ui Thread un ClusterManager.addItem () mais ces éléments ne sont pas peints dans la carte, seulement quand je fais une mise à jour de zoom ( + , -) sont affichés. Aussi, j'ai essayé de déboguer le renderer, mais onBeforeClusterRendered / onBeforeClusterItemRendered ne sont pas appelés jusqu'à ce que je mette à jour le zoom dans la carte. Des idées pour rafraîchir la carte / clusterManager / marqueurs?

        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);
18
demandé sur PaNaVTEC 2014-03-09 23:45:22

7 réponses

mClusterManager.cluster ();

force de re-classification des éléments lorsque vous après avoir ajouté un nouvel élément.

24
répondu Oscar Kuok 2014-03-14 02:52:10

Semble que j'en ai trouvé une solution de contournement.

ClusterManager utilise un renderer, dans ce cas il hérite de DefaultClusterRenderer qui utilise un cache interne, un cache de marqueurs qui sont ajoutés à la carte. Vous pouvez accéder directement aux marqueurs ajoutés sur la carte, je n'utilise pas la fenêtre info, donc j'ajoute des options de marqueur.titre() un ID pour trouver plus tard ce marqueur, de sorte que:

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

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


}

et quand je veux recharger la clusterItem j'appelle cette méthode:

/**
  * 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;
            }
        }

    }

Peut-être est un peu hacky mais ça marche et je n'ai pas trouvé d'autre moyen de faire ça. Si vous avez trouvé un autre meilleur, merci de partager :)

15
répondu PaNaVTEC 2014-03-10 10:04:10

j'ai eu le même problème. Il a également été aggravé par le fait que je fais un rendu personnalisé dans onBeforeClusterItemRendered sur ma DefaultClusterRenderer sous-classe.

ma solution a été de créer une nouvelle instance de ma sous-classe DefaultClusterRenderer et d'appeler setRenderer sur le ClusterManager à nouveau. Cette balise toutes les icônes cachées et recrée tout.

C'est hacky, la force brute et fâcheusement inefficace, mais il fonctionne. C'était la seule approche que j'ai trouvé qui a travaillé depuis la bibliothèque ne semble pas avoir de prise en charge explicite.

2
répondu Jonathan 2014-09-17 16:31:47

Vous pouvez obtenir des marqueurs spécifiques qui correspondent à leurs articles cluster ou cluster et vice versa en O (1) en utilisant Defaultclusterrenderer's getMarker (), getCluster () et getClusterItem () (définissez votre propre renderer pour accéder à l'objet renderer).

Utilisez ces méthodes pour changer les marqueurs de vos articles chaque fois que vous avez besoin.

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

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

cependant, je ne recommande pas de les sauvegarder ailleurs, puisque ces méthodes renvoient les objets de cache du rendeur.

2
répondu user3687289 2015-08-20 12:25:26

mClusterManager.cluster(); n'a pas fonctionné pour moi

ce n':

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

cela a déclenché un appel onCameraChange, où je faisais déjà mClusterManager.clearItems ()... mClusterManager.addItem(..) - pour les objets à l'intérieur de la région visible... mClusterManager.cluster ()

le contexte pour moi était que les pins disparaissaient en retournant au fragment affichant la carte (- seulement sur certains appareils comme Nexus 7, où il n'y avait pas d'appel automatique à OnCameraChange)

2
répondu hmac 2015-11-04 09:18:29

j'ai eu exactement le même problème. Aucune des solutions proposées ne fonctionnait pour moi. J'ai fait une classe qui étend le DefaultClusterRenderer et ajoute la méthode publique updateClusterItem(ClusterItem clusterItem) qui va forcer le marqueur associé à ce ClusterItem à être re-rendu (fonctionne à la fois avec les articles de cluster et cluster).

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());
    }

}
2
répondu John Langone 2016-08-17 21:50:33

ma solution avec un CustomRenderer qui étend DefaultClusterRenderer

 protected void onClusterItemRendered(T clusterItem, Marker marker) {
    marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
-1
répondu Ciprian 2015-10-18 21:25:25