Skip to content

Commit 7ed6692

Browse files
authored
feat: add controls for light and dark modes (#548)
1 parent 1ce882b commit 7ed6692

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2305
-521
lines changed

README.md

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ in an unbounded widget will cause the application to throw a Flutter exception.
9595

9696
You can also add a bare GoogleMapsMapView that works as a normal map view without navigation functionality.
9797

98-
### Add a navigation view
98+
### Add a navigation view and start a navigation session
9999

100100
```dart
101101
import 'package:flutter/material.dart';
@@ -199,7 +199,7 @@ This parameter has only an effect on Android.
199199
200200
```
201201

202-
#### Using Map IDs
202+
### Using Map IDs
203203
You can configure your map by providing a `mapId` parameter during map initialization. Map IDs are created in the [Google Cloud Console](https://console.cloud.google.com/google/maps-apis/studio/maps) and allow you to [enable various Google Maps Platform features](https://developers.google.com/maps/documentation/android-sdk/map-ids/mapid-over#features-available), such as cloud-based map styling.
204204

205205
> [!NOTE]
@@ -262,6 +262,89 @@ Widget build(BuildContext context) {
262262
}
263263
```
264264

265+
### Controlling Light and Dark Mode
266+
267+
The SDK provides two different settings to control the appearance of maps and navigation UI: `mapColorScheme` and `forceNightMode`. Which setting to use depends on whether navigation UI is enabled or disabled.
268+
269+
These settings can be configured both during initialization and dynamically changed after initialization using the view controllers.
270+
271+
#### For Navigation Views (GoogleMapsNavigationView)
272+
273+
**When navigation UI is enabled:**
274+
- Use `forceNightMode` (or `initialForceNightMode` during initialization) to control both the navigation UI elements and the map tile colors.
275+
- The `mapColorScheme` setting is ignored when navigation UI is enabled.
276+
277+
> [!TIP]
278+
> When navigation guidance is running, it's recommended to use `NavigationForceNightMode.auto` (the default). This allows the Navigation SDK to automatically determine the appropriate day or night mode based on the user's location and local time, which may differ from the device's system settings.
279+
280+
```dart
281+
GoogleMapsNavigationView(
282+
initialForceNightMode: NavigationForceNightMode.auto,
283+
initialMapColorScheme: MapColorScheme.dark, // IGNORED when navigation UI is enabled
284+
)
285+
```
286+
287+
To manually force a specific mode:
288+
```dart
289+
GoogleMapsNavigationView(
290+
initialForceNightMode: NavigationForceNightMode.forceNight,
291+
)
292+
```
293+
294+
You can also change the setting dynamically after initialization:
295+
296+
```dart
297+
// Change after initialization when navigation UI is enabled
298+
await navigationViewController.setForceNightMode(NavigationForceNightMode.forceNight);
299+
```
300+
301+
**When navigation UI is disabled:**
302+
- Use `mapColorScheme` (or `initialMapColorScheme` during initialization) to control the map tile colors.
303+
- The `forceNightMode` setting has no effect when navigation UI is disabled.
304+
305+
```dart
306+
GoogleMapsNavigationView(
307+
initialNavigationUIEnabledPreference: NavigationUIEnabledPreference.disabled,
308+
initialMapColorScheme: MapColorScheme.dark,
309+
initialForceNightMode: NavigationForceNightMode.forceDay // IGNORED when navigation UI is disabled
310+
)
311+
```
312+
313+
You can also change the setting dynamically after initialization:
314+
315+
```dart
316+
// Change after initialization when navigation UI is disabled
317+
await navigationViewController.setMapColorScheme(MapColorScheme.dark);
318+
```
319+
320+
#### For Map Views (GoogleMapsMapView)
321+
322+
Map views only support `mapColorScheme` to control the map tile colors:
323+
324+
```dart
325+
GoogleMapsMapView(
326+
initialMapColorScheme: MapColorScheme.dark,
327+
)
328+
```
329+
330+
You can also change the setting dynamically after initialization:
331+
332+
```dart
333+
// Change after initialization
334+
await mapViewController.setMapColorScheme(MapColorScheme.dark);
335+
```
336+
337+
#### Available Options
338+
339+
- `NavigationForceNightMode`:
340+
- `auto` (default and recommended) - SDK determines day/night mode based on user's location and local time
341+
- `forceDay` - Force day mode regardless of time or location
342+
- `forceNight` - Force night mode regardless of time or location
343+
- `MapColorScheme`:
344+
- `followSystem` (default) - Follow device system settings
345+
- `light` - Force light color scheme
346+
- `dark` - Force dark color scheme
347+
265348
## Support for Android Auto and Apple CarPlay
266349
This plugin is compatible with both Android Auto and Apple CarPlay infotainment systems. For more details, please refer to the respective platform documentation:
267350

android/src/main/kotlin/com/google/maps/flutter/navigation/Convert.kt

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.google.android.gms.maps.model.Gap
2828
import com.google.android.gms.maps.model.JointType
2929
import com.google.android.gms.maps.model.LatLng
3030
import com.google.android.gms.maps.model.LatLngBounds
31+
import com.google.android.gms.maps.model.MapColorScheme
3132
import com.google.android.gms.maps.model.PatternItem
3233
import com.google.android.gms.maps.model.Polygon
3334
import com.google.android.gms.maps.model.Polyline
@@ -41,6 +42,7 @@ import com.google.android.libraries.mapsplatform.turnbyturn.model.NavState
4142
import com.google.android.libraries.mapsplatform.turnbyturn.model.StepInfo
4243
import com.google.android.libraries.navigation.AlternateRoutesStrategy
4344
import com.google.android.libraries.navigation.DisplayOptions
45+
import com.google.android.libraries.navigation.ForceNightMode
4446
import com.google.android.libraries.navigation.NavigationRoadStretchRenderingData
4547
import com.google.android.libraries.navigation.NavigationTrafficData
4648
import com.google.android.libraries.navigation.Navigator
@@ -82,6 +84,7 @@ object Convert {
8284
options.minZoomPreference?.let { googleMapOptions.minZoomPreference(it.toFloat()) }
8385
options.maxZoomPreference?.let { googleMapOptions.maxZoomPreference(it.toFloat()) }
8486
googleMapOptions.zoomControlsEnabled(options.zoomControlsEnabled)
87+
googleMapOptions.mapColorScheme(convertMapColorSchemeFromDto(options.mapColorScheme))
8588
options.mapId?.let { googleMapOptions.mapId(it) }
8689

8790
return MapOptions(googleMapOptions, options.padding)
@@ -114,7 +117,8 @@ object Convert {
114117

115118
return NavigationViewOptions(
116119
navigationUiEnabledPreference =
117-
convertNavigationUIEnabledPreferenceFromDto(options.navigationUIEnabledPreference)
120+
convertNavigationUIEnabledPreferenceFromDto(options.navigationUIEnabledPreference),
121+
forceNightMode = convertNavigationForceNightModeFromDto(options.forceNightMode),
118122
)
119123
}
120124

@@ -279,6 +283,63 @@ object Convert {
279283
}
280284
}
281285

286+
/**
287+
* Converts pigeon [MapColorSchemeDto] to [MapColorScheme].
288+
*
289+
* @param mapColorScheme pigeon [MapColorSchemeDto].
290+
* @return [MapColorScheme].
291+
*/
292+
fun convertMapColorSchemeFromDto(mapColorScheme: MapColorSchemeDto): Int {
293+
return when (mapColorScheme) {
294+
MapColorSchemeDto.FOLLOW_SYSTEM -> MapColorScheme.FOLLOW_SYSTEM
295+
MapColorSchemeDto.LIGHT -> MapColorScheme.LIGHT
296+
MapColorSchemeDto.DARK -> MapColorScheme.DARK
297+
}
298+
}
299+
300+
/**
301+
* Converts [MapColorScheme] to pigeon [MapColorSchemeDto].
302+
*
303+
* @param mapColorScheme [MapColorScheme].
304+
* @return pigeon [MapColorSchemeDto].
305+
*/
306+
fun convertMapColorSchemeToDto(mapColorScheme: Int): MapColorSchemeDto {
307+
return when (mapColorScheme) {
308+
MapColorScheme.LIGHT -> MapColorSchemeDto.LIGHT
309+
MapColorScheme.DARK -> MapColorSchemeDto.DARK
310+
else -> MapColorSchemeDto.FOLLOW_SYSTEM
311+
}
312+
}
313+
314+
/**
315+
* Converts pigeon [NavigationForceNightModeDto] to [ForceNightMode].
316+
*
317+
* @param forceNightMode pigeon [NavigationForceNightModeDto].
318+
* @return [ForceNightMode].
319+
*/
320+
fun convertNavigationForceNightModeFromDto(forceNightMode: NavigationForceNightModeDto): Int {
321+
return when (forceNightMode) {
322+
NavigationForceNightModeDto.AUTO -> ForceNightMode.AUTO
323+
NavigationForceNightModeDto.FORCE_DAY -> ForceNightMode.FORCE_DAY
324+
NavigationForceNightModeDto.FORCE_NIGHT -> ForceNightMode.FORCE_NIGHT
325+
}
326+
}
327+
328+
/**
329+
* Converts [ForceNightMode] to pigeon [NavigationForceNightModeDto].
330+
*
331+
* @param forceNightMode [ForceNightMode].
332+
* @return pigeon [NavigationForceNightModeDto].
333+
*/
334+
fun convertNavigationForceNightModeToDto(forceNightMode: Int): NavigationForceNightModeDto {
335+
return when (forceNightMode) {
336+
ForceNightMode.AUTO -> NavigationForceNightModeDto.AUTO
337+
ForceNightMode.FORCE_DAY -> NavigationForceNightModeDto.FORCE_DAY
338+
ForceNightMode.FORCE_NIGHT -> NavigationForceNightModeDto.FORCE_NIGHT
339+
else -> throw FlutterError("convertError", "Unknown ForceNightMode: $forceNightMode")
340+
}
341+
}
342+
282343
/**
283344
* Converts pigeon [NavigationWaypointDto] to Google Navigation [Waypoint].
284345
*

android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsBaseMapView.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,4 +1055,12 @@ abstract class GoogleMapsBaseMapView(
10551055
fun getPadding(): MapPaddingDto {
10561056
return _mapOptions?.padding ?: MapPaddingDto(0, 0, 0, 0)
10571057
}
1058+
1059+
fun getMapColorScheme(): Int {
1060+
return getMap().mapColorScheme
1061+
}
1062+
1063+
fun setMapColorScheme(mapColorScheme: Int) {
1064+
getMap().mapColorScheme = mapColorScheme
1065+
}
10581066
}

android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsNavigationView.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.content.Context
2020
import android.content.res.Configuration
2121
import android.view.View
2222
import com.google.android.gms.maps.CameraUpdateFactory
23+
import com.google.android.libraries.navigation.ForceNightMode
2324
import com.google.android.libraries.navigation.NavigationView
2425
import com.google.android.libraries.navigation.OnNavigationUiChangedListener
2526
import com.google.android.libraries.navigation.PromptVisibilityChangedListener
@@ -38,6 +39,7 @@ internal constructor(
3839
private val _navigationView: NavigationView = NavigationView(context, mapOptions.googleMapOptions)
3940

4041
/// Default values for UI features.
42+
private var _forceNightMode: Int = ForceNightMode.AUTO
4143
private var _isNavigationTripProgressBarEnabled: Boolean = false
4244
private var _isNavigationHeaderEnabled: Boolean = true
4345
private var _isNavigationFooterEnabled: Boolean = true
@@ -76,6 +78,12 @@ internal constructor(
7678
}
7779
_navigationView.isNavigationUiEnabled = navigationViewEnabled
7880

81+
// Initialize force night mode if provided
82+
navigationOptions?.forceNightMode?.let { forceNightMode ->
83+
_forceNightMode = forceNightMode
84+
_navigationView.setForceNightMode(forceNightMode)
85+
}
86+
7987
viewRegistry.registerNavigationView(viewId, this)
8088

8189
_navigationView.getMapAsync { map ->
@@ -288,4 +296,13 @@ internal constructor(
288296
fun showRouteOverview() {
289297
_navigationView.showRouteOverview()
290298
}
299+
300+
fun getForceNightMode(): Int {
301+
return _forceNightMode
302+
}
303+
304+
fun setForceNightMode(forceNightMode: Int) {
305+
_forceNightMode = forceNightMode
306+
_navigationView.setForceNightMode(forceNightMode)
307+
}
291308
}

android/src/main/kotlin/com/google/maps/flutter/navigation/GoogleMapsViewMessageHandler.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,4 +519,24 @@ class GoogleMapsViewMessageHandler(private val viewRegistry: GoogleMapsViewRegis
519519
override fun getPadding(viewId: Long): MapPaddingDto {
520520
return getView(viewId.toInt()).getPadding()
521521
}
522+
523+
override fun getMapColorScheme(viewId: Long): MapColorSchemeDto {
524+
val colorScheme = getView(viewId.toInt()).getMapColorScheme()
525+
return Convert.convertMapColorSchemeToDto(colorScheme)
526+
}
527+
528+
override fun setMapColorScheme(viewId: Long, mapColorScheme: MapColorSchemeDto) {
529+
val colorScheme = Convert.convertMapColorSchemeFromDto(mapColorScheme)
530+
getView(viewId.toInt()).setMapColorScheme(colorScheme)
531+
}
532+
533+
override fun getForceNightMode(viewId: Long): NavigationForceNightModeDto {
534+
val forceNightMode = getNavigationView(viewId.toInt()).getForceNightMode()
535+
return Convert.convertNavigationForceNightModeToDto(forceNightMode)
536+
}
537+
538+
override fun setForceNightMode(viewId: Long, forceNightMode: NavigationForceNightModeDto) {
539+
val nightMode = Convert.convertNavigationForceNightModeFromDto(forceNightMode)
540+
getNavigationView(viewId.toInt()).setForceNightMode(nightMode)
541+
}
522542
}

android/src/main/kotlin/com/google/maps/flutter/navigation/NavigationViewConfiguration.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ enum class NavigationUIEnabledPreference {
2626
}
2727

2828
/** Class for navigation view configuration options. */
29-
data class NavigationViewOptions(val navigationUiEnabledPreference: NavigationUIEnabledPreference?)
29+
data class NavigationViewOptions(
30+
val navigationUiEnabledPreference: NavigationUIEnabledPreference?,
31+
val forceNightMode: Int?,
32+
)

0 commit comments

Comments
 (0)