【问题标题】:Clustering map markers on zoom out and unclustering on zoom in缩小时聚类地图标记,放大时去聚类
【发布时间】:2014-01-21 19:55:59
【问题描述】:

我正在使用 Google Map Android clustering Utitlity 和 Google Maps v2 播放服务。

我没有得到预期的行为。正如您在下面的两张图片中看到的那样,当放大时,我可以看到 20 个集群和一个向左上方的单个标记,但是当我缩小直到它们彼此重叠时,我没有看到它们集群。 . 20 簇仍然说 20 而不是 21?

这是预期的行为吗?有没有办法可以让集群显示 21 而不是 20+

【问题讨论】:

    标签: android google-maps-android-api-2 android-maps-v2


    【解决方案1】:

    这是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);
    }
    

    请注意,标记的文本是根据bucket 选择的,而不是cluster 中的确切项目数

    对此的快速解决方法是将描述符创建修改为:

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

    当然,您可以实现您的自定义ClasterRenderer 并将其提供给ClusterManager。这样,您将负责标记的渲染,但如果您只想将 "20+" 更改为 "21" - 我会采用第一种方法

    编辑:

    解决 cmets 中提出的问题: 如果您想增加/减少分组项目的距离阈值 - 您可以修改用于聚类的default algorithm。只需使用这个常量(在你的情况下应该更小):

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

    但正确的解决方法是考虑标记位图大小而不是常量值。我假设Mr. Broadfood 把它作为给爱好者的家庭作业:)

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

    【讨论】:

    • 快速侧面问题 Pavel,因为您似乎有使用此实用程序的经验。我注意到它的分组标记在当前缩放级别中并不完全重叠。关于这个实用程序的文档似乎很少。如何设置标记在分组/聚类之前的接近程度范围
    • 再次感谢 Pavel,您是否有创建和处理 Cluster/ClusterItem(s) 选定状态的经验? the render creates an icon it seems, and i want to be able to change the view and pass a dyanmic image into that view, when a given item or cluster is selected, as well as change all the unselected back to their unselected/original state ..我浏览了图书馆,似乎找不到选择/未选择状态在哪里..
    • 是的,我看到了,但这没有考虑到集群实用程序。我会潜入水中看看我发现了什么。这个库的文档不多
    • 我尝试了这个解决方案,但渲染效果不是很好,但这是一个很好的解决方案,我如何改进渲染??
    【解决方案2】:

    您可以更改最小集群大小。默认情况下,最小集群大小为 4,在 map-utils 库中定义如下。

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

    或者您可以在扩展的 DefaultClusterRenderer 类中覆盖 shouldRenderAsCluster 方法,如下所示:

    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        // Always render clusters.
        return cluster.getSize() > 1;
    }
    

    【讨论】:

      【解决方案3】:

      我知道这是一个老问题,但对于那些仍在使用 Pavel 出色答案的人,还要确保更改这两行代码

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

      像这样更换存储桶:

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

      否则在合并/分离时集群将四舍五入到最接近的桶大小,从而导致桶大小不准确。

      一种明显的修复,但如果您不注意数据的确切值,很容易错过。

      对于任何挣扎的人:

      在保留 Google 渲染算法的同时实现 Pavel 答案的最简单方法是下载默认渲染器(如正确答案中的链接),修改代码,并将其设置为 ClusterManager 的自定义渲染器。该库对外部修改/覆盖不友好,仅覆盖此段是一件非常痛苦的事情,因为它使用了许多其他私有方法和变量。

      【讨论】:

        【解决方案4】:

        对于正在努力做同样事情的人.. 在您的自定义渲染器中覆盖这两个函数,如下所示 @覆盖 protected int getBucket(Cluster cluster) { 返回 cluster.getSize(); }

        @Override
        protected String getClusterText(int bucket) {
            return String.valueOf(bucket);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-05
          • 2021-10-29
          • 1970-01-01
          • 2018-11-25
          • 2013-09-21
          • 2021-08-10
          • 2012-12-17
          • 2013-01-08
          相关资源
          最近更新 更多