Search code examples
androidgoogle-maps-android-api-2android-maps-v2

Clustering map markers on zoom out and unclustering on zoom in


I am using the Google Map Android clustering Utitlity With Google Maps v2 play services.

I am not getting the behavior I expected. As you can see in the two images below, when zoomed in I can see a cluster of 20 and a single marker up an to the left, but when i zoom out til they are on top of each other i am not seeing them cluster.. the 20 cluster still says 20 and not 21?

enter image description here

enter image description here

Is that expected behavior? Is there a way can make the cluster show 21 instead of 20+


Solution

  • This is default behavior specified in DefaultClasterRenderer#onBeforeClusterRendered():

    /**
     * Called before the marker for a Cluster is added to the map.
     * The default implementation draws a circle with a rough count of the number of items.
     */
    protected void onBeforeClusterRendered(Cluster<T> cluster, MarkerOptions markerOptions) {
        int bucket = getBucket(cluster);
        BitmapDescriptor descriptor = mIcons.get(bucket);
        if (descriptor == null) {
            mColoredCircleBackground.getPaint().setColor(getColor(bucket));
            descriptor = BitmapDescriptorFactory.fromBitmap(mIconGenerator.makeIcon(getClusterText(bucket)));
            mIcons.put(bucket, descriptor);
        }
        // TODO: consider adding anchor(.5, .5) (Individual markers will overlap more often)
        markerOptions.icon(descriptor);
    }
    

    Note that text for the marker is chosen based on the bucket, rather than exact number of items in cluster

    The quick fix for that would be to modify descriptor creation to be something like:

    descriptor = BitmapDescriptorFactory.fromBitmap(mIconGenerator.
                                                     makeIcon(cluster.getSize());
    

    Of course you can implement your custom ClasterRenderer and provide it to the ClusterManager. In this way you will be in charge of rendering of your markers, but if you want to just change the "20+" to "21" - I would go with first approach

    EDIT:

    Addressing question asked in comments: If you want to increase/decrease distance threshold for grouping items - you can modify default algorithm used for clustering. Just play with this constant (in your case should be smaller):

    public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp.
    

    But the correct fix would be to take into account Marker bitmap size rather than constant value. I assume Mr. Broadfood left that as a homework to enthusiasts :)

    private Bounds createBoundsFromSpan(Point p, double span) {
        // TODO: Use a span that takes into account the visual size of the marker, not just its
        // LatLng.
        double halfSpan = span / 2;
        return new Bounds(
                p.x - halfSpan, p.x + halfSpan,
                p.y - halfSpan, p.y + halfSpan);
    }