diff --git a/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt b/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt index 3e3cfabb6..0fd27819c 100644 --- a/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt @@ -176,6 +176,7 @@ fun GoogleMapView( onClick = markerClick ) MarkerComposable( + title = "Marker Composable", keys = arrayOf("singapore4"), state = singapore4State, onClick = markerClick, diff --git a/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt b/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt index ad5e5a24a..54ebaad15 100644 --- a/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt +++ b/maps-compose-utils/src/main/java/com/google/maps/android/compose/clustering/Clustering.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.launch * @param clusterContent an optional Composable that is rendered for each [Cluster]. * @param clusterItemContent an optional Composable that is rendered for each non-clustered item. */ + @Composable @GoogleMapComposable @MapsComposeExperimentalApi @@ -52,8 +53,8 @@ public fun Clustering( clusterContent: @[UiComposable Composable] ((Cluster) -> Unit)? = null, clusterItemContent: @[UiComposable Composable] ((T) -> Unit)? = null, ) { - val clusterManager = rememberClusterManager(clusterContent, clusterItemContent) ?: return + val clusterManager = rememberClusterManager(clusterContent, clusterItemContent) ?: return ResetMapListeners(clusterManager) SideEffect { clusterManager.setOnClusterClickListener(onClusterClick) @@ -62,8 +63,8 @@ public fun Clustering( clusterManager.setOnClusterItemInfoWindowLongClickListener(onClusterItemInfoWindowLongClick) } InputHandler( - onMarkerClick = clusterManager::onMarkerClick, - onInfoWindowClick = clusterManager::onInfoWindowClick, + onMarkerClick = clusterManager.markerManager::onMarkerClick, + onInfoWindowClick = clusterManager.markerManager::onInfoWindowClick, onInfoWindowLongClick = clusterManager.markerManager::onInfoWindowLongClick, onMarkerDrag = clusterManager.markerManager::onMarkerDrag, onMarkerDragEnd = clusterManager.markerManager::onMarkerDragEnd, diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/MapApplier.kt b/maps-compose/src/main/java/com/google/maps/android/compose/MapApplier.kt index 7f8ece37b..a1df579b5 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/MapApplier.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/MapApplier.kt @@ -72,61 +72,69 @@ internal class MapApplier( map.setOnCircleClickListener { circle -> decorations.findInputCallback( nodeMatchPredicate = { it.circle == circle }, + marker = circle, nodeInputCallback = { onCircleClick }, inputHandlerCallback = { onCircleClick } - )?.invoke(circle) + ) } map.setOnGroundOverlayClickListener { groundOverlay -> decorations.findInputCallback( nodeMatchPredicate = { it.groundOverlay == groundOverlay }, nodeInputCallback = { onGroundOverlayClick }, + marker = groundOverlay, inputHandlerCallback = { onGroundOverlayClick } - )?.invoke(groundOverlay) + ) } map.setOnPolygonClickListener { polygon -> decorations.findInputCallback( nodeMatchPredicate = { it.polygon == polygon }, nodeInputCallback = { onPolygonClick }, + marker = polygon, inputHandlerCallback = { onPolygonClick } - )?.invoke(polygon) + ) } map.setOnPolylineClickListener { polyline -> decorations.findInputCallback( nodeMatchPredicate = { it.polyline == polyline }, nodeInputCallback = { onPolylineClick }, + marker = polyline, inputHandlerCallback = { onPolylineClick } - )?.invoke(polyline) + ) } // Marker map.setOnMarkerClickListener { marker -> decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { onMarkerClick }, inputHandlerCallback = { onMarkerClick } - )?.invoke(marker) + ) ?: false } map.setOnInfoWindowClickListener { marker -> decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { onInfoWindowClick }, inputHandlerCallback = { onInfoWindowClick } - )?.invoke(marker) + ) } map.setOnInfoWindowCloseListener { marker -> decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { onInfoWindowClose }, inputHandlerCallback = { onInfoWindowClose } - )?.invoke(marker) + ) } map.setOnInfoWindowLongClickListener { marker -> decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { onInfoWindowLongClick }, inputHandlerCallback = { onInfoWindowLongClick } - )?.invoke(marker) + ) } map.setOnMarkerDragListener(object : GoogleMap.OnMarkerDragListener { override fun onMarkerDrag(marker: Marker) { @@ -138,13 +146,15 @@ internal class MapApplier( markerState.dragState = DragState.DRAG } }, + marker = marker, inputHandlerCallback = { onMarkerDrag } - )?.invoke(marker) + ) } override fun onMarkerDragEnd(marker: Marker) { decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { { markerState.position = it.position @@ -152,12 +162,13 @@ internal class MapApplier( } }, inputHandlerCallback = { onMarkerDragEnd } - )?.invoke(marker) + ) } override fun onMarkerDragStart(marker: Marker) { decorations.findInputCallback( nodeMatchPredicate = { it.marker == marker }, + marker = marker, nodeInputCallback = { { markerState.position = it.position @@ -165,7 +176,7 @@ internal class MapApplier( } }, inputHandlerCallback = { onMarkerDragStart } - )?.invoke(marker) + ) } }) map.setInfoWindowAdapter( @@ -181,25 +192,29 @@ internal class MapApplier( } /** - * General pattern for handling input: - * Find the node that belongs to the clicked item. - * If there is none, default to the first InputHandlerNode. + * General pattern for handling input. This finds the node that belongs to the clicked item, and executes the callback. + * * If there is none, don't handle. */ private inline fun Iterable.findInputCallback( nodeMatchPredicate: (NodeT) -> Boolean, nodeInputCallback: NodeT.() -> ((I) -> O)?, + marker : I, inputHandlerCallback: InputHandlerNode.() -> ((I) -> O)?, -): ((I) -> O)? { - var callback: ((I) -> O)? = null +): Boolean { + var callback: ((I) -> O)? for (item in this) { if (item is NodeT && nodeMatchPredicate(item)) { // Found a matching node - return nodeInputCallback(item) + nodeInputCallback(item)?.invoke(marker) + return true } else if (item is InputHandlerNode) { // Found an input handler, but keep looking for matching nodes callback = inputHandlerCallback(item) + if (callback?.invoke(marker) == true) { + return true + } } } - return callback + return false }