Clustering map markers on zoom out and unclustering on zoom in

前端 未结 4 1321
南旧
南旧 2020-12-30 17:19

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

相关标签:
4条回答
  • 2020-12-30 17:54

    I realize this is an old question, but for those still using Pavel's excellent answer, also make sure that you change these two lines of code

    BitmapDescriptor descriptor = mIcons.get(cluster.getSize());
    ...
    mIcons.put(bucket, descriptor);
    

    replacing bucket like so:

    BitmapDescriptor descriptor = mIcons.get(cluster.getSize());
    ...
    mIcons.put(cluster.getSize(), descriptor);
    

    Otherwise clusters will be rounding to the nearest bucket size when merging/separating resulting in inaccurate bucket sizes.

    Kind of an obvious fix, but very easy to miss if you aren't paying attention to the exact values of your data.

    For anyone struggling:

    The simplest way to implement Pavel's answer while retaining Google's rendering algorithm is to download the default renderer (as linked in Correct Answer), modify the code, and set it as a custom renderer for your ClusterManager. The library is not friendly to external modification / overwriting, and it's a colossal pain in the butt to only overwrite this segment, because it uses so many other private methods and variables.

    0 讨论(0)
  • 2020-12-30 17:57

    For someone who is struggling to do the same.. in your custom renderer override these two function as below @Override protected int getBucket(Cluster cluster) { return cluster.getSize(); }

    @Override
    protected String getClusterText(int bucket) {
        return String.valueOf(bucket);
    }
    
    0 讨论(0)
  • 2020-12-30 18:05

    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);
    }
    
    0 讨论(0)
  • 2020-12-30 18:11

    You can change your minimum cluster size. By Default minimum cluster size is 4 defined in map-utils library as below.

        /**
         * If cluster size is less than this size, display individual markers.
         */
        private int mMinClusterSize = 4;
    
        /**
         * Determine whether the cluster should be rendered as individual markers or a cluster.
         */
        protected boolean shouldRenderAsCluster(Cluster<T> cluster) {
            return cluster.getSize() > mMinClusterSize;
        }
    

    Or you can override shouldRenderAsCluster method in your extended DefaultClusterRenderer class as below:

    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        // Always render clusters.
        return cluster.getSize() > 1;
    }
    
    0 讨论(0)
提交回复
热议问题