【问题标题】:Disable clustering at max zoom level using android-maps-utils使用 android-maps-utils 在最大缩放级别禁用集群
【发布时间】:2016-07-17 00:38:02
【问题描述】:

我是新来的,欢迎提供任何反馈。我正在尝试使用 DefaultClusterRenderer 来显示一些自定义集群,并且我试图让它在地图完全放大时不集群。所以我找到了完全相同问题的答案: Disable clustering at max zoom level with Googles android-maps-utils 所以我尝试了该代码,但我收到了 Not on the main thread 错误。任何帮助将不胜感激。 我的构造函数中有这个

public EspecieRenderer(Context context, GoogleMap map, ClusterManager<T> clusterManager) {
    super(context, map, clusterManager);
    this.mMap = map;
...
}

然后我在做

@Override
protected boolean shouldRenderAsCluster(Cluster<T> cluster) {
    final float currentZoom = mMap.getCameraPosition().zoom;
    final float currentMaxZoom = mMap.getMaxZoomLevel();
    return currentZoom < currentMaxZoom && cluster.getSize() >= 10;
}

这是我初始化集群的方式。我使用线程是因为我要加载近 200 个物种,每个物种都有一个或多个标记要添加到地图中

private void setUpClusterer() {
    clusterManager = new ClusterManager<>(this, googleMap);
    clusterManager.setRenderer(new EspecieRenderer<>(this, googleMap, clusterManager));
    googleMap.setOnCameraChangeListener(clusterManager);
    googleMap.setOnMarkerClickListener(clusterManager);
    ArrayList<Especie> especies = (ArrayList<Especie>) Especie.list(this);
    for (Especie especie : especies) {
        ExecutorService queue = Executors.newSingleThreadExecutor();
        queue.execute(new EspecieLoader(this, especie));
    }
}

EspecieLoader 在哪里

public class EspecieLoader implements Runnable {
    private MainActivity context;
    private Especie especie;

    public EspecieLoader(MainActivity mainActivity, Especie especie) {
        this.context = mainActivity;
        this.especie = especie;
    }

    @Override
    public void run() {
        List<Foto> fotos = Foto.findAllByEspecieWithdCoords(context, especie);
        String nombre = especie.getNombreCientifico();
        for (Foto foto : fotos) {
            LatLng latLng = new LatLng(foto.getLatitud(), foto.getLongitud());
            Bitmap bitmap;
            String path = "new/" + foto.getPath().replaceAll("-", "_").toLowerCase();
            try {
                bitmap = ResourcesHelper.getEncyclopediaAssetByName(context, path);
                EspecieMarker especieMarker = new EspecieMarker(nombre, bitmap, latLng);
                context.addSpeciesMarker(especieMarker);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

当我尝试运行我的应用程序时,我得到了这个:

07-16 19:18:41.402 31151-32075/com.lzm.Cajas E/AndroidRuntime: FATAL EXCEPTION: Thread-47332
Process: com.lzm.Cajas, PID: 31151
java.lang.IllegalStateException: Not on the main thread
    2at maps.f.g.b(Unknown Source)
    at maps.z.F.a(Unknown Source)
    at maps.af.t.a(Unknown Source)
    at vl.onTransact(:com.google.android.gms.DynamiteModulesB:51)
    at android.os.Binder.transact(Binder.java:387)
    at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.getCameraPosition(Unknown Source)
    at com.google.android.gms.maps.GoogleMap.getCameraPosition(Unknown Source)
    at com.lzm.Cajas.map.EspecieRenderer.shouldRenderAsCluster(EspecieRenderer.java:62)
    at com.google.maps.android.clustering.view.DefaultClusterRenderer$RenderTask.run(DefaultClusterRenderer.java:416)
    at java.lang.Thread.run(Thread.java:818)

【问题讨论】:

  • 您能说明一下您是如何初始化集群管理器并向其中添加项目的吗?
  • 我已经用集群的初始化更新了我的问题
  • 问题是你必须在主线程上添加标记,而不是Runnable
  • 好的,谢谢,我会试着告诉你进展如何

标签: android google-maps google-maps-api-3


【解决方案1】:

2022 年更新 - 由于之前的答案有点混乱,而且谷歌地图的相机事件发生了变化,这里有一个更新和优雅的解决方案:

扩展ClusterManager end 公开一个属性,该属性指示标记是否应根据缩放级别进行聚类并在onCameraIdle 事件中更新。

open class ZoomClusterManager<T : ClusterItem>(
    context: Context,
    private val map: GoogleMap
) : ClusterManager<T>(context, map) {
    companion object {
        private const val CLUSTER_MAX_ZOOM_LEVEL = 9
    }

    private var _shouldClusterZoom: Boolean = true
    val shouldClusterZoom get() = _shouldClusterZoom

    override fun onCameraIdle() {
        super.onCameraIdle()
        _shouldClusterZoom = map.cameraPosition.zoom < CLUSTER_MAX_ZOOM_LEVEL
    }
}

根据用例,您可能希望将CLUSTER_MAX_ZOOM_LEVEL 作为构造函数中的属性,以便更好地重用类。
然后也扩展DefaultClusterRenderer。在构造函数中传递您的 ClusterManager 扩展版本,覆盖 shouldRenderAsCluster 并检查之前公开的属性,如下所示:

open class ZoomClusterRenderer<T : ClusterItem>(
    context: Context,
    map: GoogleMap,
    private val clusterManager: ZoomClusterManager<T>
) : DefaultClusterRenderer<T>(context, map, clusterManager) {

    override fun shouldRenderAsCluster(cluster: Cluster<T>): Boolean {
        return super.shouldRenderAsCluster(cluster) && clusterManager.shouldClusterZoom
    }
}

最后将所有内容连接到您要设置地图的片段中:

val clusterManager = ZoomClusterManager<ClusterItem>(requireContext(), googleMap)
clusterManager.renderer = ZoomClusterRenderer(requireContext(), googleMap, clusterManager)
googleMap.setOnCameraIdleListener(clusterManager)

旧答案 - 我今天也遇到了同样的需求。这是我的解决方案: 既然不能设置两次 setOnCameraChangeListener,那就去掉

googleMap.setOnCameraChangeListener(clusterManager);

替换成

googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {
            shouldCluster_zoom = cameraPosition.zoom < 9; //disables the cluster at 9 and higher zoom levels
            clusterManager.onCameraChange(cameraPosition); //Replaces googleMap.setOnCameraChangeListener(clusterManager);
        }
    });

"shouldCluster_zoom" 显然是一个全局变量,静态和布尔值。 现在在“shouldRenderAsCluster”方法中检查,根据缩放,标记是否应该聚集:

    @Override
    protected boolean shouldRenderAsCluster(Cluster<T> cluster) {
        return super.shouldRenderAsCluster(cluster) && Your_class_name.shouldCluster_zoom;
    }

【讨论】:

  • 我会试一试,让你知道
  • @luzma 所以?它是否有效?请给我们您的反馈
  • lib 应该添加这个选项。应该很方便
【解决方案2】:

在@Alberto97 的回答之上进行编辑:

OnCameraChange 方法现已弃用。他们用三个摄像头监听器替换了 GoogleMap.OnCameraChangeListener():

  • GoogleMap.OnCameraMoveStartedListener - 相机运动开始时的回调接口。
  • GoogleMap.OnCameraMoveListener - 相机改变位置时的回调接口。
  • GoogleMap.OnCameraIdleListener - 相机移动结束时的回调接口。

我会使用 OnCameraIdleListener

  googleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
            @Override
            public void onCameraIdle() {
                shouldCluster_zoom = cameraPosition.zoom < 9;
                clusterManager.onCameraIdle();
            }
        });

【讨论】:

    猜你喜欢
    • 2015-12-30
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多