diff --git a/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt b/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt index 14905244..88a15f97 100644 --- a/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt +++ b/maps-app/src/main/java/com/google/maps/android/compose/BasicMapActivity.kt @@ -162,7 +162,7 @@ fun GoogleMapView( var shouldAnimateZoom by remember { mutableStateOf(true) } var ticker by remember { mutableIntStateOf(0) } var mapProperties by remember { - mutableStateOf(MapProperties(mapType = MapType.NORMAL)) + mutableStateOf(MapProperties(isTrafficEnabled = true, mapType = MapType.NORMAL)) } var mapVisible by remember { mutableStateOf(true) } diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt b/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt index d0266903..62271ad4 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/GoogleMap.kt @@ -37,7 +37,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle @@ -242,8 +241,6 @@ private fun CoroutineScope.launchSubcomposition( composition.setContent { MapUpdater(mapUpdaterState) - MapClickListenerUpdater() - CompositionLocalProvider( LocalCameraPositionState provides mapUpdaterState.cameraPositionState, content 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 f1793069..7da59018 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 @@ -75,6 +75,22 @@ internal class MapApplier( } internal fun attachClickListeners() { + with(mapClickListeners) { + map.setOnIndoorStateChangeListener(object : GoogleMap.OnIndoorStateChangeListener { + override fun onIndoorBuildingFocused() = + indoorStateChangeListener.onIndoorBuildingFocused() + + override fun onIndoorLevelActivated(building: com.google.android.gms.maps.model.IndoorBuilding) = + indoorStateChangeListener.onIndoorLevelActivated(building) + }) + map.setOnMapClickListener { onMapClick?.invoke(it) } + map.setOnMapLongClickListener { onMapLongClick?.invoke(it) } + map.setOnMapLoadedCallback { onMapLoaded?.invoke() } + map.setOnMyLocationButtonClickListener { onMyLocationButtonClick?.invoke() ?: false } + map.setOnMyLocationClickListener { onMyLocationClick?.invoke(it) } + map.setOnPoiClickListener { onPOIClick?.invoke(it) } + } + map.setOnCircleClickListener { circle -> decorations.findInputCallback( nodeMatchPredicate = { it.circle == circle }, diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt b/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt index 42b3ee6e..55f2cbaa 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/MapClickListeners.kt @@ -68,129 +68,3 @@ internal class MapClickListeners { var onMyLocationClick: ((Location) -> Unit)? by mutableStateOf(null) var onPOIClick: ((PointOfInterest) -> Unit)? by mutableStateOf(null) } - -/** - * @param L GoogleMap click listener type, e.g. [OnMapClickListener] - */ -internal class MapClickListenerNode( - private val map: GoogleMap, - private val setter: GoogleMap.(L?) -> Unit, - private val listener: L -) : MapNode { - override fun onAttached() = setListener(listener) - override fun onRemoved() = setListener(null) - override fun onCleared() = setListener(null) - - private fun setListener(listenerOrNull: L?) = map.setter(listenerOrNull) -} - -@Suppress("ComplexRedundantLet") -@Composable -internal fun MapClickListenerUpdater() { - // The mapClickListeners container object is not allowed to ever change - val mapClickListeners = (currentComposer.applier as MapApplier).mapClickListeners - - with(mapClickListeners) { - ::indoorStateChangeListener.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnIndoorStateChangeListener, - object : OnIndoorStateChangeListener { - override fun onIndoorBuildingFocused() = - callback().onIndoorBuildingFocused() - - override fun onIndoorLevelActivated(building: IndoorBuilding) = - callback().onIndoorLevelActivated(building) - } - ) - } - - ::onMapClick.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnMapClickListener, - OnMapClickListener { callback()?.invoke(it) } - ) - } - - ::onMapLongClick.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnMapLongClickListener, - OnMapLongClickListener { callback()?.invoke(it) } - ) - } - - ::onMapLoaded.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnMapLoadedCallback, - OnMapLoadedCallback { callback()?.invoke() } - ) - } - - ::onMyLocationButtonClick.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnMyLocationButtonClickListener, - OnMyLocationButtonClickListener { callback()?.invoke() ?: false } - ) - } - - ::onMyLocationClick.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnMyLocationClickListener, - OnMyLocationClickListener { callback()?.invoke(it) } - ) - } - - ::onPOIClick.let { callback -> - MapClickListenerComposeNode( - callback, - GoogleMap::setOnPoiClickListener, - OnPoiClickListener { callback()?.invoke(it) } - ) - } - } -} - -/** - * Encapsulates the ComposeNode factory lambda as a recomposition optimization. - * - * @param L GoogleMap click listener type, e.g. [OnMapClickListener] - * @param callback a property reference to the callback lambda, i.e. - * invoking it returns the callback lambda - * @param setter a reference to a GoogleMap setter method, e.g. `setOnMapClickListener()` - * @param listener must include a call to `callback()` inside the listener - * to use the most up-to-date recomposed version of the callback lambda; - * However, the resulting callback reference might actually be null due to races; - * the caller must guard against this case. - * - */ -@Composable -@NonRestartableComposable -private fun MapClickListenerComposeNode( - callback: () -> Any?, - setter: GoogleMap.(L?) -> Unit, - listener: L -) { - val mapApplier = currentComposer.applier as MapApplier - - MapClickListenerComposeNode(callback) { MapClickListenerNode(mapApplier.map, setter, listener) } -} - -@Composable -@GoogleMapComposable -private fun MapClickListenerComposeNode( - callback: () -> Any?, - factory: () -> MapClickListenerNode<*> -) { - // Setting a GoogleMap listener may have side effects, so we unset it as needed. - // However, the listener is reset only when the corresponding callback lambda - // toggles between null and non-null. This is to avoid potential performance problems - // when callbacks recompose rapidly; setting GoogleMap listeners could potentially be - // expensive due to synchronization, etc. GoogleMap listeners are not designed with a - // use case of rapid recomposition in mind. - if (callback() != null) ComposeNode, MapApplier>(factory) {} -}