kotlin Jetpack Compose上的GoogleMap聚类问题

krcsximq  于 2022-11-30  发布在  Kotlin
关注(0)|答案(1)|浏览(217)

我正在尝试开发一个应用程序,使用谷歌Map来显示一些位置。我试图实现标记聚类的标记非常接近。但是,这样做的标记点击,以显示一个信息窗口不再工作。如果有人能告诉我一个trun周围,我会非常感谢。这是我的代码。

GoogleMap(
            modifier = Modifier
                .fillMaxSize(),
            cameraPositionState = cameraPositionState,
            uiSettings = uiSettings,
            onMapClick = {
                onMapClick(it)
            }
        ) {
            var clusterManager by remember {
                mutableStateOf<ClusterManager<CustomMarkerState>?>(
                    null
                )
            }
            MapEffect(listOfMarkers) { map ->
                if (clusterManager == null) {
                    clusterManager = ClusterManager<CustomMarkerState>(context, map)
                }
                clusterManager?.addItems(listOfMarkers)
            }
            LaunchedEffect(key1 = cameraPositionState.isMoving) {
                if (!cameraPositionState.isMoving) {
                    clusterManager?.onCameraIdle()
                }
            }
            if (listOfMarkers.isNotEmpty()) {
                listOfMarkers.forEach { marker ->
                        Marker(
                            state = MarkerState(
                                position = LatLng(
                                    marker.latitude,
                                    marker.longitude
                                )
                            ),
                            title = marker.name,
                            snippet = marker.description,
                            onClick = {
                                isShown = true
                                selectedMarker = marker
                                return@Marker true
                            }
                        )
                    } 
                }
            }
        }
qv7cva1a

qv7cva1a1#

制作您自己的群集渲染,这是完整的解决方案

package com.google.maps.android.compose

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.maps.android.clustering.ClusterItem
import com.google.maps.android.clustering.ClusterManager

private val singapore = LatLng(1.35, 103.87)
private val singapore2 = LatLng(2.50, 103.87)

class MapClusteringActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            GoogleMapClustering()
        }
    }

    fun showToast(msg: String) {
        Toast.makeText(this@MapClusteringActivity, msg, Toast.LENGTH_SHORT).show()
    }

    @Composable
    fun GoogleMapClustering() {
        val items = remember { mutableStateListOf<MyItem>() }
        LaunchedEffect(Unit) {
            for (i in 1..10) {
                val position = LatLng(
                    singapore2.latitude + kotlin.random.Random.nextFloat(),
                    singapore2.longitude + kotlin.random.Random.nextFloat(),
                )
                items.add(MyItem(position, "Marker", "Snippet"))
            }

           
        }
        GoogleMapClustering(items = items)
    }

    @OptIn(MapsComposeExperimentalApi::class)
    @Composable
    fun GoogleMapClustering(items: List<MyItem>) {
        val cameraPositionState = rememberCameraPositionState {
            position = CameraPosition.fromLatLngZoom(singapore, 10f)
        }
        GoogleMap(
            modifier = Modifier.fillMaxSize(),
            cameraPositionState = cameraPositionState
        ) {
            val context = LocalContext.current
            var clusterManager by remember { mutableStateOf<ClusterManager<MyItem>?>(null) }
            MapEffect(items) { map ->
                if (clusterManager == null) {
                    clusterManager = ClusterManager<MyItem>(context, map)
                }
                clusterManager?.addItems(items)
                clusterManager?.renderer = MarkerClusterRender(context,map,clusterManager!!) {
                    showToast(it.itemTitle)
                }
            }
            LaunchedEffect(key1 = cameraPositionState.isMoving) {
                if (!cameraPositionState.isMoving) {
                    clusterManager?.onCameraIdle()
                }
            }
        }

    }
}

data class MyItem(
    val itemPosition: LatLng,
    val itemTitle: String,
    val itemSnippet: String,
) : ClusterItem {
    override fun getPosition(): LatLng =
        itemPosition

    override fun getTitle(): String =
        itemTitle

    override fun getSnippet(): String =
        itemSnippet
}

自定义群集管理器

package com.google.maps.android.compose

import android.content.Context
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.Marker
import com.google.maps.android.clustering.Cluster
import com.google.maps.android.clustering.ClusterItem
import com.google.maps.android.clustering.ClusterManager
import com.google.maps.android.clustering.view.DefaultClusterRenderer

class MarkerClusterRender<T : ClusterItem>(
    var context: Context,
    var googleMap: GoogleMap,
    clusterManager: ClusterManager<T>,
    var onInfoWindowClick: (MyItem) -> Unit
) :
    DefaultClusterRenderer<T>(context, googleMap, clusterManager) {

    private var clusterMap: HashMap<String, Marker> = hashMapOf()

    override fun shouldRenderAsCluster(cluster: Cluster<T>): Boolean {
        return cluster.size > 1
    }

    override fun getBucket(cluster: Cluster<T>): Int {
        return cluster.size
    }

    override fun getClusterText(bucket: Int): String {
        return super.getClusterText(bucket).replace("+", "")
    }

    override fun onClusterItemRendered(clusterItem: T, marker: Marker) {
        super.onClusterItemRendered(clusterItem, marker)
        clusterMap[(clusterItem as MyItem).itemTitle] = marker

        setMarker((clusterItem as MyItem), marker)
    }

    private fun setMarker(poi: MyItem, marker: Marker?) {
        val markerColor = BitmapDescriptorFactory.HUE_RED
        marker?.let {
            it.tag = poi
            it.showInfoWindow()
            changeMarkerColor(it, markerColor)
        }
        googleMap.setOnInfoWindowClickListener {
            onInfoWindowClick(it.tag as MyItem)
        }
    }

    private fun getClusterMarker(itemId: String): Marker? {
        return if (clusterMap.containsKey(itemId)) clusterMap[itemId]
        else null
    }

    fun showRouteInfoWindow(key: String) {
        getClusterMarker(key)?.showInfoWindow()
    }

    private fun changeMarkerColor(marker: Marker, color: Float) {
        try {
            marker.setIcon(BitmapDescriptorFactory.defaultMarker(color));
        } catch (ex: IllegalArgumentException) {
            ex.printStackTrace()
        } catch (ex: Exception) {
            ex.printStackTrace()
        }
    }

}

相关问题