generic_map
Shared map models and behavior with a Google Maps renderer for Flutter. Supports Android, iOS and web. Native desktop rendering is not supported.
The abstraction provides camera movement and bounds fitting, Flutter widget
markers rendered as cached bitmaps, polylines, circles, heatmaps, editable
polygons, place picking, and debounced reverse geocoding. It uses the
gm_google_maps_flutter fork for editable shapes.
Install
dependencies:
generic_map: ^0.17.1
latlong2: ^0.9.1
Configure your Google Maps API keys in the Android/iOS runner and load the Google Maps JavaScript API on web, as described in the Google Maps setup guide.
import 'package:generic_map/generic_map.dart';
import 'package:latlong2/latlong.dart';
GenericMap(
interactive: true,
initialLocation: const Place(
LatLng(37.7858, -122.4064), 'San Francisco, CA', 'San Francisco',
),
googleMapOptions: const GoogleMapsOptions(
preset: GoogleMapStylePreset.dark,
),
onControllerReady: (controller) {
controller.fitBounds(points);
},
)
Shared API
MapViewController:fitBounds,moveCamera,setCamera,getCenter,getViewportBounds, anddispose.MapViewCamera: center, zoom, bearing and tilt;setCameraoptionally takes an animation duration.MapMovedEvent: position, bounds, zoom, bearing, movement stage and movement source. UseisUserGestureto distinguish dragging from programmatic moves.CustomMarker: widget, position, alignment, rotation, flat/upright orientation, and tap callback. Supply a stablecacheKeyto reuse unchanged bitmaps.PolyLineLayer,CircleMarker,HeatmapConfig,Place,AddressResolver.LatLngBounds: owned by generic_map rather than a rendering dependency. UsefromSouthWestNorthEastwhen reading a viewport crossing the antimeridian.
A place picker uses MapViewMode.picker, interactive: true, a
centerMarkerBuilder and an addressResolver. Enable enableAddressResolve
to receive resolved addresses. Camera idle and address callbacks are debounced;
new movement cancels pending work.
For editable polygons, set isPolylineDrawEnabled: true, pass
initialDrawingPoints, and handle onPolylineDrawn. Updating the points also
updates the polygon, so a host can implement undo/redo. Existing editable
polylines use onPolylineEdited.
Google styles include standard, silver, retro, dark, night and aubergine. A
customStyleJson overrides the preset. GoogleMapsOptions.buildingsEnabled
controls 3D buildings; dark presets disable them by default.
Match the app's appearance on iOS
Google Maps inherits its native window's appearance on iOS. A standard/light JSON style alone does not force light appearance when the device is dark. For apps with a Light/Dark/System setting, wrap the app once:
NativeMapAppearance(
themeMode: selectedThemeMode,
child: MaterialApp(
themeMode: selectedThemeMode,
theme: lightTheme,
darkTheme: darkTheme,
home: const HomeScreen(),
),
)
Pass the stored ThemeMode, including ThemeMode.system. Do not derive it from
Theme.of(context).brightness: System must remove the native override to follow
subsequent device appearance changes. Continue selecting map presets from the
resolved Flutter theme as usual.
This is an explicit app-wide native appearance opt-in: other native controls also inherit the chosen mode. Use one wrapper above the app, rather than one per map. Android and web are unchanged. No AppDelegate edits or additional map SDKs are required. Rebuild the iOS app after adding/upgrading the package; hot reload alone cannot install the native plugin. Swift Package Manager integration uses Flutter 3.44 or later; older Flutter projects can use CocoaPods.
Migrating from 0.16
Version 0.17 removes the Mapbox, flutter_map and disabled MapLibre renderers. Their SDKs, tile caching and editor packages are no longer dependencies.
- Remove
mapboxOptions,mapboxSdkOptions,mapLibreOptions,openStreetMapOptionsanduseCachedTilesarguments. - Replace
polyEditor: PolyEditor(points: points, ...)withinitialDrawingPoints: pointsand use the drawing/edit callbacks. LatLngBoundsnow comes from generic_map. Code using its constructors, corners, cardinal edges, center andcontainskeeps the same spelling. Other flutter_map-specific APIs must be migrated explicitly.- Remove direct flutter_map/tile-cache dependencies and cache initialization from your application too, otherwise they remain installed.
- Use
MapProviderEnum.supportedValuesin provider pickers. Legacy enum identifiers andPlatformMapProviderSettingsremain readable for stored settings, but all selections resolve to Google Maps. Applications should normalize persisted selections togoogleMapswhen restoring settings. - Native desktop no longer has a fallback renderer.
GenericMaprenders an empty widget there and does not callonControllerReady; hide map-dependent controls on those platforms or use the web app.
A future provider should ship as a separately installed adapter so applications only include the SDKs they use.
Development
flutter pub get
flutter analyze lib test example/lib
flutter test
The small example in example/lib/main.dart uses Google Maps. Configure its
platform keys before running it. Native map behavior must also be checked on a
simulator/device or browser; unit tests cover shared camera, bounds, marker
caching, padding and movement-source behavior.
Libraries
- extensions
- generic_map
- google_map/controller
- google_map/google_map
- google_map/marker_generator
- google_map/marker_generator_v2
- google_map/options
- google_map/padding
- google_map/parser
- google_map/widget
- interfaces/address_resolver
- interfaces/base_parser
- interfaces/center_marker
- interfaces/circle_marker
- interfaces/heat_map_config
- interfaces/interfaces
- interfaces/lat_lng_bounds
- interfaces/latlng_distance_to
- interfaces/map_controller
- interfaces/map_move_source
- interfaces/map_provider_enum
- interfaces/map_view_camera
- interfaces/map_view_mode
- interfaces/marker
- interfaces/place
- interfaces/polyline_layer
- native_map_appearance
- platform_map_provider_settings
- utils/widget_to_image
- widget