Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android如何在集群标记上单击一次即可取消集群映射v2_Android_Google Maps - Fatal编程技术网

Android如何在集群标记上单击一次即可取消集群映射v2

Android如何在集群标记上单击一次即可取消集群映射v2,android,google-maps,Android,Google Maps,我正在使用谷歌地图标记聚类实用程序对标记进行聚类。它在双击时松开。是否可以一次单击就手动执行此操作。晚会有点晚了 mClusterManager .setOnClusterClickListener(new OnClusterClickListener<MyItem>() { @Override public boolean onClusterClick(final Cluster<

我正在使用谷歌地图标记聚类实用程序对标记进行聚类。它在双击时松开。是否可以一次单击就手动执行此操作。

晚会有点晚了

    mClusterManager
            .setOnClusterClickListener(new OnClusterClickListener<MyItem>() {
                @Override
                public boolean onClusterClick(final Cluster<MyItem> cluster) {
                    map.animateCamera(CameraUpdateFactory.newLatLngZoom(
                            cluster.getPosition(), (float) Math.floor(map
                                    .getCameraPosition().zoom + 1)), 300,
                            null);
                    return true;
                }
            });
在onClusterClick函数中:

LatLngBounds.Builder builder = LatLngBounds.builder();
for (ClusterItem item : cluster.getItems()) {
    builder.include(item.getPosition());
}
final LatLngBounds bounds = builder.build();
getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));

对于希望扩展群集并保持缩放级别的用户,请尝试以下步骤。这似乎很复杂,但事实并非如此

台阶
  • 假设您有一个名为Location的模型,该模型实现了ClusterItem,请添加以下代码:

    private boolean shouldCluster = true;
    
    public boolean isShouldCluster() {
        return shouldCluster;
    }
    
    public void setShouldCluster(boolean shouldCluster) {
        this.shouldCluster = shouldCluster;
    }
    
    整个模型与此类似:

    public class Location implements ClusterItem
    {
        private double latitude;
    
        private double longitude;
    
        private boolean shouldCluster = true;
    
        @Override
        public LatLng getPosition() {
            return new LatLng(latitude, longitude);
        }
    
        @Override
        public String getTitle() {
            return null;
        }
    
        @Override
        public String getSnippet() {
            return null;
        }
    
        public boolean isShouldCluster() {
            return shouldCluster;
        }
    
        public void setShouldCluster(boolean shouldCluster) {
            this.shouldCluster = shouldCluster;
        }
    }
    
  • 将下面的算法添加到项目中,并将位置替换为您自己的模型名称。注意:这个算法只是谷歌的一个副本,经过一些修改

    public class DistanceBasedAlgorithm implements Algorithm<Location> {
        public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp.
    
        /**
         * Any modifications should be synchronized on mQuadTree.
         */
        private final Collection<QuadItem> mItems = new ArrayList<QuadItem>();
    
        /**
         * Any modifications should be synchronized on mQuadTree.
         */
        private final PointQuadTree<QuadItem> mQuadTree = new PointQuadTree<QuadItem>(0, 1, 0, 1);
    
        private static final SphericalMercatorProjection PROJECTION = new SphericalMercatorProjection(1);
    
        @Override
        public void addItem(Location item) {
            if (item == null) return;
    
            final QuadItem quadItem = new QuadItem(item);
            synchronized (mQuadTree) {
                mItems.add(quadItem);
                mQuadTree.add(quadItem);
            }
        }
    
        @Override
        public void addItems(Collection<Location> items) {
            for (Location item : items) {
                addItem(item);
            }
        }
    
        @Override
        public void clearItems() {
            synchronized (mQuadTree) {
                mItems.clear();
                mQuadTree.clear();
            }
        }
    
        @Override
        public void removeItem(Location item) {
            // QuadItem delegates hashcode() and equals() to its item so,
            //   removing any QuadItem to that item will remove the item
            final QuadItem quadItem = new QuadItem(item);
            synchronized (mQuadTree) {
                mItems.remove(quadItem);
                mQuadTree.remove(quadItem);
            }
        }
    
        @Override
        public Set<? extends Cluster<Location>> getClusters(double zoom) {
            final int discreteZoom = (int) zoom;
    
            final double zoomSpecificSpan = MAX_DISTANCE_AT_ZOOM / Math.pow(2, discreteZoom) / 256;
    
            final Set<QuadItem> visitedCandidates = new HashSet<QuadItem>();
            final Set<Cluster<Location>> results = new HashSet<Cluster<Location>>();
            final Map<QuadItem, Double> distanceToCluster = new HashMap<QuadItem, Double>();
            final Map<QuadItem, StaticCluster<Location>> itemToCluster = new HashMap<QuadItem, StaticCluster<Location>>();
    
            synchronized (mQuadTree) {
                for (QuadItem candidate : mItems) {
                    if (visitedCandidates.contains(candidate)) {
                        // Candidate is already part of another cluster.
                        continue;
                    }
    
                    Collection<QuadItem> clusterItems;
    
                    if (candidate.mClusterItem.isShouldCluster()) {
                        Bounds searchBounds = createBoundsFromSpan(candidate.getPoint(), zoomSpecificSpan);
                        clusterItems = mQuadTree.search(searchBounds);
                    }
                    else {
                        List<QuadItem> temp = new ArrayList<>();
                        temp.add(candidate);
                        clusterItems = temp;
                    }
    
                    if (clusterItems.size() == 1) {
                        // Only the current marker is in range. Just add the single item to the results.
                        results.add(candidate);
                        visitedCandidates.add(candidate);
                        distanceToCluster.put(candidate, 0d);
                        continue;
                    }
                    StaticCluster<Location> cluster = new StaticCluster<Location>(candidate.mClusterItem.getPosition());
                    results.add(cluster);
    
                    for (QuadItem clusterItem : clusterItems) {
                        Double existingDistance = distanceToCluster.get(clusterItem);
                        double distance = distanceSquared(clusterItem.getPoint(), candidate.getPoint());
                        if (existingDistance != null) {
                            // Item already belongs to another cluster. Check if it's closer to this cluster.
                            if (existingDistance < distance) {
                                continue;
                            }
                            // Move item to the closer cluster.
                            itemToCluster.get(clusterItem).remove(clusterItem.mClusterItem);
                        }
                        distanceToCluster.put(clusterItem, distance);
                        cluster.add(clusterItem.mClusterItem);
                        itemToCluster.put(clusterItem, cluster);
                    }
                    visitedCandidates.addAll(clusterItems);
                }
            }
            return results;
        }
    
        @Override
        public Collection<Location> getItems() {
            final List<Location> items = new ArrayList<Location>();
            synchronized (mQuadTree) {
                for (QuadItem quadItem : mItems) {
                    items.add(quadItem.mClusterItem);
                }
            }
            return items;
        }
    
        private double distanceSquared(Point a, Point b) {
            return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
        }
    
        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);
        }
    
        private static class QuadItem implements PointQuadTree.Item, Cluster<Location> {
            private final Location mClusterItem;
            private final Point mPoint;
            private final LatLng mPosition;
            private Set<Location> singletonSet;
    
            private QuadItem(Location item) {
                mClusterItem = item;
                mPosition = item.getPosition();
                mPoint = PROJECTION.toPoint(mPosition);
                singletonSet = Collections.singleton(mClusterItem);
            }
    
            @Override
            public Point getPoint() {
                return mPoint;
            }
    
            @Override
            public LatLng getPosition() {
                return mPosition;
            }
    
            @Override
            public Set<Location> getItems() {
                return singletonSet;
            }
    
            @Override
            public int getSize() {
                return 1;
            }
    
            @Override
            public int hashCode() {
                return mClusterItem.hashCode();
            }
    
            @Override
            public boolean equals(Object other) {
                if (!(other instanceof QuadItem)) {
                    return false;
                }
    
                return ((QuadItem) other).mClusterItem.equals(mClusterItem);
            }
        }
    }
    

  • 我已经有一段时间没有写代码了。我可能会错过什么。如果您在解决此问题时遇到困难,请给我留言。谢谢

    非常感谢你。成功了!没有想过获取当前缩放并增加它。但是这会取消集群中的“所有”项目吗?我不认为当有这么多的集群项目时,将缩放比例增加1就可以了。这并不能回答问题,你可以用正确的方式增加缩放比例:
    CameraUpdateFactory.zoomIn()
    CameraUpdateFactory.zoomTo()
    CameraUpdateFactory.zoomBy()
    如何再次启用集群?单击群集后,您设置了shouldcluster(false),但如何在地图滚动或任何其他操作中启用它?@NickUnuchek,已经有一段时间了。我记不起细节了。我相信DistanceBasedAlgorithm.getClusters会重新创建所有项目,当应用操作时,默认情况下应该将Cluster设置为true。在我们的产品中,我们没有任何重新分类的问题。
    public class DistanceBasedAlgorithm implements Algorithm<Location> {
        public static final int MAX_DISTANCE_AT_ZOOM = 100; // essentially 100 dp.
    
        /**
         * Any modifications should be synchronized on mQuadTree.
         */
        private final Collection<QuadItem> mItems = new ArrayList<QuadItem>();
    
        /**
         * Any modifications should be synchronized on mQuadTree.
         */
        private final PointQuadTree<QuadItem> mQuadTree = new PointQuadTree<QuadItem>(0, 1, 0, 1);
    
        private static final SphericalMercatorProjection PROJECTION = new SphericalMercatorProjection(1);
    
        @Override
        public void addItem(Location item) {
            if (item == null) return;
    
            final QuadItem quadItem = new QuadItem(item);
            synchronized (mQuadTree) {
                mItems.add(quadItem);
                mQuadTree.add(quadItem);
            }
        }
    
        @Override
        public void addItems(Collection<Location> items) {
            for (Location item : items) {
                addItem(item);
            }
        }
    
        @Override
        public void clearItems() {
            synchronized (mQuadTree) {
                mItems.clear();
                mQuadTree.clear();
            }
        }
    
        @Override
        public void removeItem(Location item) {
            // QuadItem delegates hashcode() and equals() to its item so,
            //   removing any QuadItem to that item will remove the item
            final QuadItem quadItem = new QuadItem(item);
            synchronized (mQuadTree) {
                mItems.remove(quadItem);
                mQuadTree.remove(quadItem);
            }
        }
    
        @Override
        public Set<? extends Cluster<Location>> getClusters(double zoom) {
            final int discreteZoom = (int) zoom;
    
            final double zoomSpecificSpan = MAX_DISTANCE_AT_ZOOM / Math.pow(2, discreteZoom) / 256;
    
            final Set<QuadItem> visitedCandidates = new HashSet<QuadItem>();
            final Set<Cluster<Location>> results = new HashSet<Cluster<Location>>();
            final Map<QuadItem, Double> distanceToCluster = new HashMap<QuadItem, Double>();
            final Map<QuadItem, StaticCluster<Location>> itemToCluster = new HashMap<QuadItem, StaticCluster<Location>>();
    
            synchronized (mQuadTree) {
                for (QuadItem candidate : mItems) {
                    if (visitedCandidates.contains(candidate)) {
                        // Candidate is already part of another cluster.
                        continue;
                    }
    
                    Collection<QuadItem> clusterItems;
    
                    if (candidate.mClusterItem.isShouldCluster()) {
                        Bounds searchBounds = createBoundsFromSpan(candidate.getPoint(), zoomSpecificSpan);
                        clusterItems = mQuadTree.search(searchBounds);
                    }
                    else {
                        List<QuadItem> temp = new ArrayList<>();
                        temp.add(candidate);
                        clusterItems = temp;
                    }
    
                    if (clusterItems.size() == 1) {
                        // Only the current marker is in range. Just add the single item to the results.
                        results.add(candidate);
                        visitedCandidates.add(candidate);
                        distanceToCluster.put(candidate, 0d);
                        continue;
                    }
                    StaticCluster<Location> cluster = new StaticCluster<Location>(candidate.mClusterItem.getPosition());
                    results.add(cluster);
    
                    for (QuadItem clusterItem : clusterItems) {
                        Double existingDistance = distanceToCluster.get(clusterItem);
                        double distance = distanceSquared(clusterItem.getPoint(), candidate.getPoint());
                        if (existingDistance != null) {
                            // Item already belongs to another cluster. Check if it's closer to this cluster.
                            if (existingDistance < distance) {
                                continue;
                            }
                            // Move item to the closer cluster.
                            itemToCluster.get(clusterItem).remove(clusterItem.mClusterItem);
                        }
                        distanceToCluster.put(clusterItem, distance);
                        cluster.add(clusterItem.mClusterItem);
                        itemToCluster.put(clusterItem, cluster);
                    }
                    visitedCandidates.addAll(clusterItems);
                }
            }
            return results;
        }
    
        @Override
        public Collection<Location> getItems() {
            final List<Location> items = new ArrayList<Location>();
            synchronized (mQuadTree) {
                for (QuadItem quadItem : mItems) {
                    items.add(quadItem.mClusterItem);
                }
            }
            return items;
        }
    
        private double distanceSquared(Point a, Point b) {
            return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
        }
    
        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);
        }
    
        private static class QuadItem implements PointQuadTree.Item, Cluster<Location> {
            private final Location mClusterItem;
            private final Point mPoint;
            private final LatLng mPosition;
            private Set<Location> singletonSet;
    
            private QuadItem(Location item) {
                mClusterItem = item;
                mPosition = item.getPosition();
                mPoint = PROJECTION.toPoint(mPosition);
                singletonSet = Collections.singleton(mClusterItem);
            }
    
            @Override
            public Point getPoint() {
                return mPoint;
            }
    
            @Override
            public LatLng getPosition() {
                return mPosition;
            }
    
            @Override
            public Set<Location> getItems() {
                return singletonSet;
            }
    
            @Override
            public int getSize() {
                return 1;
            }
    
            @Override
            public int hashCode() {
                return mClusterItem.hashCode();
            }
    
            @Override
            public boolean equals(Object other) {
                if (!(other instanceof QuadItem)) {
                    return false;
                }
    
                return ((QuadItem) other).mClusterItem.equals(mClusterItem);
            }
        }
    }
    
    map.setOnMarkerClickListener(mClusterManager);
    mClusterManager.setAlgorithm(new DistanceBasedAlgorithm());
    mClusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<Location>() {
                @Override
                public boolean onClusterClick(Cluster<Location> cluster) {
                    for (Location location : cluster.getItems()) {
                        location.setShouldCluster(false);
                    }
                    mClusterManager.addItem(null); // this line resets the cache
                    mClusterManager.cluster(); // re-cluster
    
                    return false;
                }
            });
    
            if (candidate.mClusterItem.isShouldCluster()) {
                Bounds searchBounds = createBoundsFromSpan(candidate.getPoint(), zoomSpecificSpan);
                clusterItems = mQuadTree.search(searchBounds);
            }
            else {
                List<QuadItem> temp = new ArrayList<>();
                temp.add(candidate);
                clusterItems = temp;
            }
    
    @Override
    public void addItem(Location item) {
        if (item == null) return; // this line is the key to reset cache
    
        final QuadItem quadItem = new QuadItem(item);
        synchronized (mQuadTree) {
            mItems.add(quadItem);
            mQuadTree.add(quadItem);
        }
    }