flutter_unified_map_flutter_map
Pure Dart implementation of flutter_unified_map on flutter_map. Used automatically on web, Windows and Linux, and in widget tests.
Default base map: OpenStreetMap raster tiles (standard, and muted desaturated), Esri World Imagery (satellite, hybrid), nothing for none. Show the attribution with RichAttributionWidget or SimpleAttributionWidget.
Configuration
The package registers a default instance. To configure it, depend on flutter_unified_map_flutter_map and flutter_unified_map_platform_interface, and install your own instance before runApp on the platforms that use it:
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_unified_map_flutter_map/flutter_unified_map_flutter_map.dart';
import 'package:flutter_unified_map_platform_interface/flutter_unified_map_platform_interface.dart';
void main() {
if (kIsWeb || defaultTargetPlatform == TargetPlatform.windows || defaultTargetPlatform == TargetPlatform.linux) {
UnifiedMapsPlatform.instance = UnifiedMapsFlutterMap(userAgentPackageName: 'com.example.app');
}
runApp(const MyApp());
}
userAgentPackageName: on Windows and Linux every tile request is sent withUser-Agent: flutter_map (<userAgentPackageName>)(browsers send their own). The OpenStreetMap tile usage policy asks every app to identify itself: set it to your app's package name. With the default,unknown, flutter_map warns in debug builds.tileProvidercreates the flutter_mapTileProviderof every tile layer, the base map included (layerisnullfor it), for caching or offline tiles. Return a new provider on each call, since aTileLayerdisposes its provider. Passlayer.headerson to it, asdefaultTileProviderdoes, or the tile layers' headers (anAuthorizationheader, for example) are not sent.
Behaviour
bearingis a compass heading, as on Google Maps and MapKit: it is the opposite of flutter_map'srotation(bearing 90 puts north on the left).- Animated camera moves pan and turn the shorter way, across the antimeridian when that is shorter.
getVisibleRegionreturns bounds that cross the antimeridian asnorthEast.longitude < southWest.longitude, and the whole world (-180 to 180) when the view is wider than it. - Padding applies from the first frame. A padding change keeps the camera target, the target of a running animation too. Narrowing
minZoom/maxZoommoves the camera into the new range, with start, move and idle events. - Any user input stops a running camera animation, the scroll wheel and arrow keys included. Arrow-key panning follows
scrollEnabledand ctrl-drag rotation followsrotateEnabled. The map never takes the keyboard focus on its own: it gets it through focus traversal (Tab). - A
tileSizeof 512 or 1024 follows the Mapbox convention (zoomOffsetof -1 or -2), as on Android and MapKit.{r}becomes@2xon screens with a pixel ratio of 2 or more, as on Android and MapKit. A tile overlay is hidden below itsminZoomand scaled up above itsmaxZoom(the core hides it aboveTileLayer.maxZoom), as on MapKit. Changing a tile overlay'sopacityorzIndexkeeps its loaded tiles. - A polyline border adds
borderWidthto the line's total width (borderWidth / 2on each side), as flutter_map'sborderStrokeWidth; the Android and Apple packages draw it the same way. Dash lengths are logical pixels, not stretched to fit the line, and a pattern with an odd number of lengths repeats whole ([10]is 10 on, 10 off), as on Android and Apple. Polylines and polygons without points are skipped. - Tile overlays, polygons, polylines and circles are stacked together by
zIndex; markers are always above them. - Marker transitions (
updateMarkers(..., transition:)) useCurves.easeInOutand move markers in a straight line on the Web Mercator plane (as flutter_map_marker_cluster's screen-space tweens), along the shorter way across the antimeridian. Each marker keeps its own timeline: a transition restarts only the markers it adds, removes or moves, from where they are on screen; markers already in flight that it does not touch finish on their own schedule. An update without a transition puts the markers it touches at their target at once, in flight or not. The time is driven by a ticker of the mounted view, so a re-parented view continues its transitions, and an unmounted view (or one sent a transition before it mounts) applies them at once. Snapshots leave disappearing markers out without any change on screen. - When the view is about as wide as the world, flutter_map draws a marker once per visible world copy.
supportsFlutterMapLayersis true: the widgets given tosetFlutterMapLayersare drawn inside theFlutterMap, above shapes and markers, in list order, so they seeMapCamera.ofandMapController.of(flutter_unified_map_marker_clusterdraws flutter_map_marker_cluster's layer this way). They are children of oneStack, matched to the previous list by key: the core wraps each layer's widgets in aKeyedSubtreekeyed by layer id and position, so a stateful layer (such asMarkerClusterLayerWidget) keeps its state when another layer is added or removed. A list set while another widget builds is drawn at the latest on the next frame.- Load events:
PlatformMapLoadedEventfollows the first base map tile, where the base map is the style's own layer or, when that is hidden (none, or areplacesBaseMaplayer), the tile layers; withnoneand no tile layer it follows the ready event. When base tiles fail and no tile of the current base map loaded in the last 10 s, onePlatformMapErrorEvent(loadFailed, naming the tile host and the exception, any URL reduced to its host) is sent until a tile loads again, which sends a new loaded event. A failed tile is requested again once it has left the view and comes back. - Camera queries (
getCamera,getVisibleRegion,toScreen,toLatLng) on a disposed view answer from its last camera (getCamerafrom its initial camera if the view never became ready). Before the view is ready,getCamerareturns the initial camera and the others throw aStateError. A view removed from the tree mid-movement ends the movement with an idle event. takeSnapshotcaptures the last painted frame: after an update, wait for a frame before taking it.
Not rendered
showsUserLocation, showsCompass, showsBuildings, showsTraffic, showsPointsOfInterest, camera tilt and PlatformPolyline.geodesic. hybrid shows imagery without labels. The gestureRecognizers argument of buildView is ignored: the map is a regular widget, not a platform view. The camera is not constrained: the map can be dragged past the poles.