Skip to content

Commit 202f34f

Browse files
authored
feat: Add the reason for map camera movement (#154)
* feat: Add the reason for map camera movement * chore: Add unit test * refactor: Convert reason from Int to Enum * chore: Don't use wildcard imports * chore: Restore import that was previously removed
1 parent 62d8234 commit 202f34f

File tree

5 files changed

+73
-1
lines changed

5 files changed

+73
-1
lines changed

app/src/androidTest/java/com/google/maps/android/compose/GoogleMapViewTests.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,13 @@ class GoogleMapViewTests {
7575
@Test
7676
fun testCameraReportsMoving() {
7777
initMap()
78+
assertEquals(CameraMoveStartedReason.NO_MOVEMENT_YET, cameraPositionState.cameraMoveStartedReason)
7879
zoom(shouldAnimate = true, zoomIn = true) {
7980
composeTestRule.waitUntil(1000) {
8081
cameraPositionState.isMoving
8182
}
8283
assertTrue(cameraPositionState.isMoving)
84+
assertEquals(CameraMoveStartedReason.DEVELOPER_ANIMATION, cameraPositionState.cameraMoveStartedReason)
8385
}
8486
}
8587

app/src/main/java/com/google/maps/android/compose/LocationTrackingActivity.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class LocationTrackingActivity : AppCompatActivity() {
6767
setContent {
6868
var isMapLoaded by remember { mutableStateOf(false) }
6969

70-
// To control the map camera
70+
// To control and observe the map camera
7171
val cameraPositionState = rememberCameraPositionState {
7272
position = defaultCameraPosition
7373
}
@@ -88,6 +88,13 @@ class LocationTrackingActivity : AppCompatActivity() {
8888
cameraPositionState.animate(CameraUpdateFactory.newCameraPosition(cameraPosition), 1_000)
8989
}
9090

91+
// Detect when the map starts moving and print the reason
92+
LaunchedEffect(cameraPositionState.isMoving) {
93+
if (cameraPositionState.isMoving) {
94+
Log.d(TAG, "Map camera started moving due to ${cameraPositionState.cameraMoveStartedReason.name}")
95+
}
96+
}
97+
9198
Box(Modifier.fillMaxSize()) {
9299
GoogleMap(
93100
modifier = Modifier.matchParentSize(),
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package com.google.maps.android.compose
15+
16+
import androidx.compose.runtime.Immutable
17+
import com.google.maps.android.compose.CameraMoveStartedReason.Companion.fromInt
18+
import com.google.maps.android.compose.CameraMoveStartedReason.NO_MOVEMENT_YET
19+
import com.google.maps.android.compose.CameraMoveStartedReason.UNKNOWN
20+
21+
/**
22+
* Enumerates the different reasons why the map camera started to move.
23+
*
24+
* Based on enum values from https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnCameraMoveStartedListener#constants.
25+
*
26+
* [NO_MOVEMENT_YET] is used as the initial state before any map movement has been observed.
27+
*
28+
* [UNKNOWN] is used to represent when an unsupported integer value is provided to [fromInt] - this
29+
* may be a new constant value from the Maps SDK that isn't supported by maps-compose yet, in which
30+
* case this library should be updated to include a new enum value for that constant.
31+
*/
32+
@Immutable
33+
public enum class CameraMoveStartedReason(public val value: Int) {
34+
UNKNOWN(-2),
35+
NO_MOVEMENT_YET(-1),
36+
GESTURE(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE),
37+
API_ANIMATION(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_API_ANIMATION),
38+
DEVELOPER_ANIMATION(com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener.REASON_DEVELOPER_ANIMATION);
39+
40+
public companion object {
41+
/**
42+
* Converts from the Maps SDK [com.google.android.gms.maps.GoogleMap.OnCameraMoveStartedListener]
43+
* constants to [CameraMoveStartedReason], or returns [UNKNOWN] if there is no such
44+
* [CameraMoveStartedReason] for the given [value].
45+
*
46+
* See https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnCameraMoveStartedListener#constants.
47+
*/
48+
public fun fromInt(value: Int): CameraMoveStartedReason {
49+
return values().firstOrNull { it.value == value } ?: return UNKNOWN
50+
}
51+
}
52+
}

maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ public class CameraPositionState(
6767
public var isMoving: Boolean by mutableStateOf(false)
6868
internal set
6969

70+
/**
71+
* The reason for the start of the most recent camera moment, or
72+
* [CameraMoveStartedReason.NO_MOVEMENT_YET] if the camera hasn't moved yet or
73+
* [CameraMoveStartedReason.UNKNOWN] if an unknown constant is received from the Maps SDK.
74+
*/
75+
public var cameraMoveStartedReason: CameraMoveStartedReason by mutableStateOf(
76+
CameraMoveStartedReason.NO_MOVEMENT_YET
77+
)
78+
internal set
79+
7080
/**
7181
* Returns the current [Projection] to be used for converting between screen
7282
* coordinates and lat/lng.

maps-compose/src/main/java/com/google/maps/android/compose/MapUpdater.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ internal class MapPropertiesNode(
6969
cameraPositionState.isMoving = false
7070
}
7171
map.setOnCameraMoveStartedListener {
72+
cameraPositionState.cameraMoveStartedReason = CameraMoveStartedReason.fromInt(it)
7273
cameraPositionState.isMoving = true
7374
}
7475
map.setOnCameraMoveListener {

0 commit comments

Comments
 (0)