Skip to content

Both copy text to your clipboard — Build with AI copies a setup prompt to paste into Claude Code, Cursor, Codex or Copilot; Copy page as Markdown copies this page to paste into a chat. How it works

Flutter — MapOptions

MapOptions is the immutable configuration object passed to MapMetricsView(options: ...). It sets the initial camera, style, zoom/pitch limits, and gesture configuration.

Coordinate order: longitude first

initCenter takes a Position(longitude, latitude) from the geotypes package — not LatLng(latitude, longitude). Getting the argument order backwards silently places the map somewhere else on Earth; nothing throws or errors.

dart
// Correct — Amsterdam is lng 4.8952, lat 52.3702:
MapOptions(initCenter: Position(4.8952, 52.3702))

// WRONG — this is lat-first and puts the map in the wrong place:
MapOptions(initCenter: Position(52.3702, 4.8952))

Sanity-check every coordinate you write: is the first number a plausible longitude (−180..180) for the place you mean, and the second a plausible latitude (−90..90)?

Constructor

dart
const MapOptions({
  this.initStyle = 'https://demotiles.maplibre.org/style.json',
  this.initZoom = 0,
  this.initCenter,
  double initPitch = 0,
  this.initBearing = 0,
  this.minZoom = 0,
  this.maxZoom = 22,
  this.minPitch = 0,
  this.maxPitch = 60,
  this.maxBounds,
  this.gestures = const MapGestures.all(),
  this.androidTextureMode = true,
  this.androidMode = AndroidPlatformViewMode.tlhc_vd,
})

Fields

FieldTypeDefaultDescription
initStyleString'https://demotiles.maplibre.org/style.json'The style URL loaded on map creation. Override this in real apps — see below for the MapMetrics gateway URL shape.
initZoomdouble0The initial zoom level.
initCenterPosition?nullThe initial map center, longitude first: Position(lng, lat).
initPitchdouble0The initial camera pitch/tilt. 0–85 on web, 0–60 on other platforms. (A deprecated pitch named parameter exists for backwards compatibility; use initPitch.)
initBearingdouble0The initial map bearing (rotation). 0 is north-up; 360 is one full loop.
minZoomdouble0The minimum allowed zoom level (0–24).
maxZoomdouble22The maximum allowed zoom level (0–24).
minPitchdouble0The minimum allowed camera pitch.
maxPitchdouble60The maximum allowed camera pitch (0–85 on web, 0–60 elsewhere; larger values are ignored on native).
maxBoundsLngLatBounds?nullRestricts the camera to this bounding box. null means no restriction.
gesturesMapGesturesconst MapGestures.all()Enables/disables individual gesture types (see below).
androidTextureModebooltrueToggles Android texture mode for the platform view. Comes at a performance cost when enabled.
androidModeAndroidPlatformViewModeAndroidPlatformViewMode.tlhc_vdThe Android platform view type used to embed the native map (see Flutter platform views).

There is no styleUrl, initialCameraPosition, myLocationEnabled, myLocationTrackingMode, compassEnabled, or trackCameraPosition field — those belong to a different, non-existent API.

Real style URL

Never ship https://demotiles.maplibre.org/style.json (the MapLibre upstream default) in a production app — it's unbranded and unversioned. Use the MapMetrics Atlas gateway:

https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY
dart
MapOptions(
  initStyle:
      'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
  initCenter: Position(4.8952, 52.3702), // Amsterdam: lng, lat
  initZoom: 12,
)

MapGestures

gestures takes a MapGestures value, which toggles four independent gesture categories:

dart
class MapGestures {
  const MapGestures({
    required this.rotate,
    required this.pan,
    required this.zoom,
    required this.pitch,
  });

  const MapGestures.all({  // every gesture enabled — the MapOptions default
    this.rotate = true,
    this.pan = true,
    this.zoom = true,
    this.pitch = true,
  });

  const MapGestures.none({ // every gesture disabled
    this.rotate = false,
    this.pan = false,
    this.zoom = false,
    this.pitch = false,
  });
}

Example — a static, non-interactive map (e.g. for a thumbnail or preview card):

dart
MapOptions(
  initCenter: Position(4.8952, 52.3702),
  initZoom: 14,
  gestures: const MapGestures.none(),
)

Or disable just rotation while keeping pan/zoom/pitch:

dart
MapOptions(
  gestures: const MapGestures(rotate: false, pan: true, zoom: true, pitch: true),
)

Restricting the camera to an area

maxBounds takes a LngLatBounds, whose fields are also longitude/latitude — but named explicitly, so there's no ordering ambiguity:

dart
MapOptions(
  initCenter: Position(9.717795, 47.504100), // Bregenz
  initZoom: 12,
  maxBounds: const LngLatBounds(
    longitudeWest: 9.589786,
    longitudeEast: 9.766498,
    latitudeSouth: 47.446159,
    latitudeNorth: 47.574776,
  ),
)

See also