diff --git a/app/src/androidTest/java/com/google/maps/android/compose/GoogleMapViewTests.kt b/app/src/androidTest/java/com/google/maps/android/compose/GoogleMapViewTests.kt index 46b72c21..fa5b8375 100644 --- a/app/src/androidTest/java/com/google/maps/android/compose/GoogleMapViewTests.kt +++ b/app/src/androidTest/java/com/google/maps/android/compose/GoogleMapViewTests.kt @@ -75,11 +75,13 @@ class GoogleMapViewTests { @Test fun testCameraReportsMoving() { initMap() + assertEquals(CameraMoveStartedReason.NO_MOVEMENT_YET, cameraPositionState.cameraMoveStartedReason) zoom(shouldAnimate = true, zoomIn = true) { composeTestRule.waitUntil(1000) { cameraPositionState.isMoving } assertTrue(cameraPositionState.isMoving) + assertEquals(CameraMoveStartedReason.DEVELOPER_ANIMATION, cameraPositionState.cameraMoveStartedReason) } } diff --git a/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt b/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt index 923562c4..2967f563 100644 --- a/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt +++ b/app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt @@ -67,7 +67,7 @@ class LocationTrackingActivity : AppCompatActivity() { setContent { var isMapLoaded by remember { mutableStateOf(false) } - // To control the map camera + // To control and observe the map camera val cameraPositionState = rememberCameraPositionState { position = defaultCameraPosition } @@ -88,6 +88,13 @@ class LocationTrackingActivity : AppCompatActivity() { cameraPositionState.animate(CameraUpdateFactory.newCameraPosition(cameraPosition), 1_000) } + // Detect when the map starts moving and print the reason + LaunchedEffect(cameraPositionState.isMoving) { + if (cameraPositionState.isMoving) { + Log.d(TAG, "Map camera started moving due to ${cameraPositionState.cameraMoveStartedReason.name}") + } + } + Box(Modifier.fillMaxSize()) { GoogleMap( modifier = Modifier.matchParentSize(), diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/CameraMoveStartedReason.kt b/maps-compose/src/main/java/com/google/maps/android/compose/CameraMoveStartedReason.kt new file mode 100644 index 00000000..4edf1b8d --- /dev/null +++ b/maps-compose/src/main/java/com/google/maps/android/compose/CameraMoveStartedReason.kt @@ -0,0 +1,52 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.maps.android.compose + +import androidx.compose.runtime.Immutable +import com.google.maps.android.compose.CameraMoveStartedReason.Companion.fromInt +import com.google.maps.android.compose.CameraMoveStartedReason.NO_MOVEMENT_YET +import com.google.maps.android.compose.CameraMoveStartedReason.UNKNOWN + +/** + * Enumerates the different reasons why the map camera started to move. + * + * Based on enum values from https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnCameraMoveStartedListener#constants. + * + * [NO_MOVEMENT_YET] is used as the initial state before any map movement has been observed. + * + * [UNKNOWN] is used to represent when an unsupported integer value is provided to [fromInt] - this + * may be a new constant value from the Maps SDK that isn't supported by maps-compose yet, in which + * case this library should be updated to include a new enum value for that constant. + */ +@Immutable +public enum class CameraMoveStartedReason(public val value: Int) { + UNKNOWN(-2), + NO_MOVEMENT_YET(-1), + GESTURE(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE), + API_ANIMATION(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_API_ANIMATION), + DEVELOPER_ANIMATION(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION); + + public companion object { + /** + * Converts from the Maps SDK [com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener] + * constants to [CameraMoveStartedReason], or returns [UNKNOWN] if there is no such + * [CameraMoveStartedReason] for the given [value]. + * + * See https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnCameraMoveStartedListener#constants. + */ + public fun fromInt(value: Int): CameraMoveStartedReason { + return values().firstOrNull { it.value == value } ?: return UNKNOWN + } + } +} \ No newline at end of file diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt b/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt index 57bdae86..0e6c893b 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt @@ -67,6 +67,16 @@ public class CameraPositionState( public var isMoving: Boolean by mutableStateOf(false) internal set + /** + * The reason for the start of the most recent camera moment, or + * [CameraMoveStartedReason.NO_MOVEMENT_YET] if the camera hasn't moved yet or + * [CameraMoveStartedReason.UNKNOWN] if an unknown constant is received from the Maps SDK. + */ + public var cameraMoveStartedReason: CameraMoveStartedReason by mutableStateOf( + CameraMoveStartedReason.NO_MOVEMENT_YET + ) + internal set + /** * Returns the current [Projection] to be used for converting between screen * coordinates and lat/lng. diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt b/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt index dca9fb4b..56ccc7f2 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt @@ -69,6 +69,7 @@ internal class MapPropertiesNode( cameraPositionState.isMoving = false } map.setOnCameraMoveStartedListener { + cameraPositionState.cameraMoveStartedReason = CameraMoveStartedReason.fromInt(it) cameraPositionState.isMoving = true } map.setOnCameraMoveListener {