sharewire / google-maps-clustering

Fast marker clustering library for Google Maps Android API.
Apache License 2.0
292 stars 77 forks source link

Add possibility to change icon of selected marker #17

Open AleksandrTabolin opened 6 years ago

AleksandrTabolin commented 6 years ago

Hi! Thank you for your work!

In app I work on I need to change icon of marker after clicked on it (make it bigger) . Now it's logic sealed in ClusterRenderer class, and there is no any posobility to change that. Easiest way to do it is add Marker from onMarkerClick method to methods of ClusterManager.Callbacks

AleksandrTabolin commented 6 years ago
public interface RenderPostProcessor<T extends ClusterItem> {
    boolean postProcess(@NonNull Marker marker, @NonNull Cluster<T> cluster);
}
public class MarkerState {

    private final Marker marker;
    private boolean isDirty;

    public MarkerState(@NonNull Marker marker, boolean isDirty) {
        this.marker = marker;
        this.isDirty = isDirty;
    }

    public MarkerState(@NonNull Marker marker) {
        this(marker, false);
    }

    @NonNull
    public Marker getMarker() {
        return marker;
    }

    public boolean isDirty() {
        return isDirty;
    }

    public void setDirty(boolean dirty) {
        isDirty = dirty;
    } 
}

in ClusterRenderer change

    private final Map<Cluster<T>, Marker> mMarkers = new HashMap<>();

to

    private final Map<Cluster<T>, MarkerState> mMarkers = new HashMap<>();

and append this to ClusterRenderer.render

void render(@NonNull List<Cluster<T>> clusters) {
        ...

        for (Map.Entry<Cluster<T>, MarkerState> item : mMarkers.entrySet()) {
            Cluster<T> cluster = item.getKey();
            MarkerState markerState = item.getValue();

            boolean isPostProcessed = mRenderPostProcessor.postProcess(markerState.getMarker(), cluster);
            if (isPostProcessed) {
                markerState.setDirty(true);
            } else if (markerState.isDirty()) {
                // there should be reset to non-dirty state
                markerState.getMarker().setIcon(getMarkerIcon(cluster));
                markerState.setDirty(false);
            }
        }
    }

and then you can do something like this

setRenderPostProcessor { marker, cluster ->
                        selectedPoint?.let { point ->
                            val needProcess = cluster.latitude == point.latitude && cluster.longitude == cluster.longitude
                            if (needProcess) {
                                val icon = if (cluster.items.size == 1) {
                                    context.bitmapDescriptorFromVector(R.drawable.ic_map_pin_active)
                                } else {
                                    BitmapDescriptorFactory
                                            .fromBitmap(selectedClusterIconGenerator.makeIcon(cluster.items.size.toString()))
                                }
                                marker.setIcon(icon)
                            }
                            needProcess
                        } ?: false
                    }
charlag commented 6 years ago

@AleksandrTabolin hi! Do you have this code published somewhere as a fork?

AleksandrTabolin commented 6 years ago

@charlag Hi! Here link to fork.

ak004 commented 2 years ago

i dont know if you will reply but i just want to change the color of the cluster marker from red to black and keep the number as it is. i did try to usedefaultIconGenerator.setIconStyle(iconStyle); but i dont knw its not working srry but im new to android and cant figure it out by myself and had to ask