Skip to content

Commit 10ffcc0

Browse files
committed
fix: fallback to moveCamera in lite mode for CameraPositionState animate
* Detect Lite Mode configuration from GoogleMapOptions to properly initialize the state * Fallback to map.moveCamera() instantaneously when animate is called in Lite Mode, which avoids suspending the coroutine indefinitely since animation callbacks are not fired * Add LiteModeActivity to the sample app to showcase the functionality and test the fallback
1 parent 3456db0 commit 10ffcc0

6 files changed

Lines changed: 101 additions & 1 deletion

File tree

maps-app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
<activity
6565
android:name=".MapsInLazyColumnActivity"
6666
android:exported="true" />
67+
<activity
68+
android:name=".LiteModeActivity"
69+
android:exported="true" />
6770
<activity
6871
android:name=".markerexamples.MarkerClusteringActivity"
6972
android:exported="true" />

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ sealed class ActivityGroup(
7575
R.string.basic_map_activity_description,
7676
BasicMapActivity::class
7777
),
78+
Activity(
79+
R.string.lite_mode_activity,
80+
R.string.lite_mode_activity_description,
81+
LiteModeActivity::class
82+
),
7883
Activity(
7984
R.string.street_view_activity,
8085
R.string.street_view_activity_description,
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.google.maps.android.compose
2+
3+
import android.os.Bundle
4+
import androidx.activity.ComponentActivity
5+
import androidx.activity.compose.setContent
6+
import androidx.activity.enableEdgeToEdge
7+
import androidx.compose.foundation.layout.Box
8+
import androidx.compose.foundation.layout.Column
9+
import androidx.compose.foundation.layout.fillMaxSize
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.systemBarsPadding
12+
import androidx.compose.material3.Button
13+
import androidx.compose.material3.Text
14+
import androidx.compose.runtime.getValue
15+
import androidx.compose.runtime.mutableStateOf
16+
import androidx.compose.runtime.remember
17+
import androidx.compose.runtime.rememberCoroutineScope
18+
import androidx.compose.ui.Modifier
19+
import androidx.compose.ui.unit.dp
20+
import com.google.android.gms.maps.CameraUpdateFactory
21+
import com.google.android.gms.maps.GoogleMapOptions
22+
import com.google.android.gms.maps.model.CameraPosition
23+
import com.google.android.gms.maps.model.LatLng
24+
import com.google.maps.android.compose.theme.MapsComposeSampleTheme
25+
import kotlinx.coroutines.launch
26+
27+
class LiteModeActivity : ComponentActivity() {
28+
29+
override fun onCreate(savedInstanceState: Bundle?) {
30+
super.onCreate(savedInstanceState)
31+
enableEdgeToEdge()
32+
setContent {
33+
MapsComposeSampleTheme {
34+
val singapore = remember { LatLng(1.35, 103.87) }
35+
val tokyo = remember { LatLng(1.35, 103.87) } // wait let me fix coords below
36+
val coroutineScope = rememberCoroutineScope()
37+
val cameraPositionState = rememberCameraPositionState {
38+
position = CameraPosition.fromLatLngZoom(singapore, 11f)
39+
}
40+
val mapProperties by remember {
41+
mutableStateOf(MapProperties(mapType = MapType.NORMAL))
42+
}
43+
44+
Column(
45+
modifier = Modifier.fillMaxSize().systemBarsPadding()
46+
) {
47+
Button(
48+
onClick = {
49+
coroutineScope.launch {
50+
// This would previously hang indefinitely in Lite Mode!
51+
// Now it falls back to instantaneous movement and completes the coroutine.
52+
val newTarget = if (cameraPositionState.position.target == singapore) {
53+
LatLng(35.6895, 139.6917) // Tokyo
54+
} else {
55+
singapore
56+
}
57+
cameraPositionState.animate(CameraUpdateFactory.newLatLng(newTarget))
58+
}
59+
},
60+
modifier = Modifier.padding(16.dp)
61+
) {
62+
Text("Animate Camera (Tests Fix)")
63+
}
64+
65+
Box(
66+
modifier = Modifier.weight(1f),
67+
) {
68+
GoogleMap(
69+
modifier = Modifier.matchParentSize(),
70+
googleMapOptionsFactory = { GoogleMapOptions().liteMode(true) },
71+
cameraPositionState = cameraPositionState,
72+
properties = mapProperties,
73+
)
74+
}
75+
}
76+
}
77+
}
78+
}
79+
}

maps-app/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
<string name="basic_map_activity">Basic Map</string>
2222
<string name="basic_map_activity_description">A simple map showing the default configuration.</string>
2323

24+
<string name="lite_mode_activity">Lite Mode Map</string>
25+
<string name="lite_mode_activity_description">A map showcasing the Lite Mode configuration.</string>
26+
2427
<string name="street_view_activity">Street View</string>
2528
<string name="street_view_activity_description">A simple Street View.</string>
2629

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public inline fun rememberCameraPositionState(
8787
public class CameraPositionState private constructor(
8888
position: CameraPosition = CameraPosition(LatLng(0.0, 0.0), 0f, 0f, 0f)
8989
) {
90+
internal var isLiteMode: Boolean = false
91+
9092
/**
9193
* Whether the camera is currently moving or not. This includes any kind of movement:
9294
* panning, zooming, or rotation.
@@ -281,6 +283,12 @@ public class CameraPositionState private constructor(
281283
durationMs: Int,
282284
continuation: CancellableContinuation<Unit>
283285
) {
286+
if (isLiteMode) {
287+
map.moveCamera(update)
288+
continuation.resume(Unit)
289+
return
290+
}
291+
284292
val cancelableCallback = object : GoogleMap.CancelableCallback {
285293
override fun onCancel() {
286294
continuation.resumeWithException(CancellationException("Animation cancelled"))

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ public fun GoogleMap(
154154
AndroidView(
155155
modifier = modifier,
156156
factory = { context ->
157-
mapViewFactory(context, googleMapOptionsFactory()).also { mapView ->
157+
val options = googleMapOptionsFactory()
158+
cameraPositionState.isLiteMode = options.liteMode == true
159+
mapViewFactory(context, options).also { mapView ->
158160
val componentCallbacks = object : ComponentCallbacks2 {
159161
override fun onConfigurationChanged(newConfig: Configuration) {}
160162

0 commit comments

Comments
 (0)