我正在尝试开发一个使用谷歌地图显示一些位置的应用程序。我尝试为非常接近的标记实现标记聚类。然而,通过这样做,点击标记以显示信息窗口不再起作用。如果有人能带我参观一下,我会非常感激的。这是我的密码。
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
}
)
}
}
}
}
制作自己的集群渲染这里是完整的解决方案
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()
}
}
}