How to Add Markers to a Flutter Map Markers turn raw latitude and longitude values into visible, tappable points on a map. They show places, vehicles, deliveries, users, or field jobs. Getting them on screen takes a few lines of code. Getting them right takes more care.

"Adding a marker" also means different things depending on your package. flutter_map renders ordinary Flutter widgets. google_maps_flutter uses native marker objects and bitmap-based icons.

This guide covers the package decision, setup, implementation steps, key marker parameters, performance, and troubleshooting.

Key Takeaways

  • flutter_map uses MarkerLayer widget children; Google Maps uses a Set<Marker> with IDs and bitmaps.
  • Valid coordinates, stable IDs, and sane marker counts drive reliable results.
  • Custom Google Maps markers usually need widgets rendered into PNG bytes.
  • Cluster, filter, or aggregate when many markers share the screen.

How to Add Markers to a Flutter Map

Step 1: Choose and configure the package

Pick flutter_map when you want provider flexibility and widget-based markers. Pick google_maps_flutter when you want Google rendering and native platform behavior.

Check version requirements before writing code. flutter_map 8.3.2 requires Flutter 3.27.0 or newer and Dart 3.6.0 or newer. The current google_maps_flutter release (2.19.0) has stricter SDK requirements, so confirm them on its pub.dev page.

Configuration differs by package:

  • flutter_map: add a TileLayer with a provider urlTemplate and set userAgentPackageName so tile servers can identify your app.
  • google_maps_flutter: enable the Maps SDKs for each platform, add API keys, and turn on billing.
    • Android key: add com.google.android.geo.API_KEY metadata to AndroidManifest.xml.
    • iOS key: import GoogleMaps in AppDelegate.swift and call GMSServices.provideAPIKey.
  • Attribution: keep provider credit visible. Public OpenStreetMap tiles require clear attribution, offer no SLA, and prohibit offline bulk use.

Step 2: Prepare marker location data

Give each marker a valid coordinate pair, a stable application ID, and optional title or metadata.

class Stop {
  final String id;
  final String title;
  final double lat;
  final double lng;
  const Stop(this.id, this.title, this.lat, this.lng);
}

Validate before rendering. Drop nulls, and reject latitudes outside -90 to 90 or longitudes outside -180 to 180.

Watch the order. Google's LatLng takes latitude first, then longitude. GeoJSON does the reverse: longitude, then latitude. Mixing them sends a Columbus, Ohio stop into the Indian Ocean.

Step 3: Add markers to the map

flutter_map (current v6+ API uses child and alignment, not the old builder):

FlutterMap(
  options: const MapOptions(
    initialCenter: LatLng(39.9612, -82.9988),
    initialZoom: 12,
  ),
  children: [
    TileLayer(
      urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      userAgentPackageName: 'com.example.app',
    ),
    MarkerLayer(
      markers: [
        const Marker(
          point: LatLng(39.9612, -82.9988),
          child: Icon(Icons.location_on, color: Colors.red, size: 30),
        ),
        Marker(
          point: const LatLng(39.9700, -83.0100),
          width: 120,
          height: 40,
          child: GestureDetector(
            onTap: () => debugPrint('Stop tapped'),
            child: Container(
              padding: const EdgeInsets.all(6),
              decoration: BoxDecoration(
                color: Colors.blue,
                borderRadius: BorderRadius.circular(8),
              ),
              child: const Text('Stop 2',
                  style: TextStyle(color: Colors.white)),
            ),
          ),
        ),
      ],
    ),
  ],
)

google_maps_flutter:

final Set<Marker> _markers = {
  const Marker(
    markerId: MarkerId('stop_1'),
    position: LatLng(39.9612, -82.9988),
    infoWindow: InfoWindow(title: 'Stop 1'),
  ),
};

GoogleMap(
  initialCameraPosition: const CameraPosition(
    target: LatLng(39.9612, -82.9988),
    zoom: 12,
  ),
  markers: _markers,
)

Use BitmapDescriptor for image icons:

  • BitmapDescriptor.asset loads asset images
  • BitmapDescriptor.bytes accepts PNG-encoded bytes
  • Older fromAssetImage and fromBytes factories are deprecated

For taps, wrap the flutter_map child in a GestureDetector or button. On Google Maps, use the marker's onTap.

Flutter map marker package implementation comparison infographic

By default, Google's marker taps also center the map and open the info window. Set consumeTapEvents: true to handle taps yourself.

Step 4: Update, test, and optimize

Keep markers in state, derived from your data list. When a vehicle moves, replace only that entry, keyed by its ID, rather than rebuilding everything.

Test these cases on each platform you support:

  • Initial load and empty responses
  • Panning and zooming
  • Marker taps
  • Different screen densities
  • Partially invalid location data

When to Add Markers and What You Need First

When markers are the right visualization

Individual markers suit small to moderate sets of meaningful points: delivery stops, service appointments, stores, or active vehicles. When points overlap heavily or update at high volume, use another technique such as clustering or aggregation.

Package and system requirements

  • Compatible Flutter and Dart SDK versions
  • Your chosen package and map widget
  • Tile provider or Google Maps configuration
  • Location permissions, if you plot the device's position
  • API credentials and billing for Google's mobile SDKs

For Google mobile targets, the current package README states Android SDK 24+ and iOS 15+. Older setup docs show lower baselines, so follow the package README. That README also marks the default iOS implementation as legacy, with migration options for newer iOS SDK versions.

Device location is a separate concern. The geolocator package needs Android fine and coarse location permissions plus NSLocationWhenInUseUsageDescription on iOS.

Data and compliance readiness

  • A defined coordinate source
  • Stable IDs
  • Fallback behavior for invalid locations
  • Labels or semantics for accessibility
  • Compliance with your provider's attribution and data-use terms

Flutter's Semantics widget works on flutter_map marker children. Semantics don't survive bitmap capture for Google markers.

Key Parameters That Affect Flutter Map Marker Results

Marker quality comes from data accuracy, rendering model, visual setup, update frequency, and how many points are in view.

Coordinate, projection, and anchor position

A reversed or null coordinate places a marker far away. A wrong anchor makes a correct coordinate look wrong.

In Google Maps, anchor defaults to Offset(0.5, 1.0), so the bottom center of the icon sits on the point. That suits pins. In flutter_map, alignment controls the pivot, and the child is centered by default. For a pin icon, shift the alignment upward so the tip lands on the point.

Marker rendering model

flutter_map markers are widgets. Dynamic text, images, and buttons work directly. Width and height default to 30 logical pixels, so larger children need explicit sizes.

Google markers are bitmaps or native objects. Custom visuals need conversion. Flutter's RenderRepaintBoundary.toImage captures a painted widget, and toByteData(format: ui.ImageByteFormat.png) produces the PNG bytes that BytesMapBitmap requires. The conversion adds lifecycle work and memory use.

Three-step Flutter custom marker widget to PNG bitmap process

Marker density and clustering

Overlapping markers hurt usability. Many widgets or native markers raise layout, render, and update costs. The flutter_map docs warn that excessive markers can cause performance problems and recommend clustering.

Options include:

  • Google's official ClusterManager, registered through clusterManagers, with a clusterManagerId on each marker
  • google_maps_cluster_manager, a community package
  • flutter_map_marker_cluster, a community add-on for flutter_map
  • Viewport filtering through getVisibleRegion or MapCamera.visibleBounds

One documented case shows how this can go wrong. Flutter issue 179456 reported slow clustered rendering with 200+ markers on web. Maintainers fixed it by batching cluster updates. That is not a universal ceiling, so profile on your own devices.

Icon dimensions, pixel ratio, and visual hierarchy

Asset resolution, pixel density, size, and contrast all affect legibility. Keep icons distinct without blotting out the map.

For generated bitmaps, toImage defaults to a pixel ratio of 1.0 regardless of device density. Set it deliberately, then size the descriptor with width, height, or imagePixelRatio.

State updates, identity, and interaction

Stable IDs let the map match old markers to new ones. Keep selected-marker state separate from the marker list so a location update doesn't reset a user's selection.

flutter_map culls offscreen children, and marker-local widget state is lost during culling. Store selection in parent state. Don't recreate every marker on each map movement or unrelated rebuild.

Common Mistakes and Troubleshooting Flutter Map Markers

Markers do not appear or appear in the wrong place

Check these first:

  1. The marker layer or collection is attached to the displayed map.
  2. The map has a valid initial center.
  3. Coordinates aren't null or reversed.
  4. Your state update actually runs.
  5. No conditional hides the marker.

Also watch for copied snippets. Version 6 of flutter_map removed builder and anchor in favor of child and alignment.

Markers lag, overlap, or disappear during updates

Likely causes include:

  • Too many markers on screen
  • Repeated rebuilds
  • Unstable marker IDs
  • Oversized custom widgets
  • Unthrottled location streams

What to try:

  • Profile performance before guessing
  • Reduce visible points or cluster them
  • Batch marker updates
  • Test behavior at several zoom levels

Custom markers fail to render or have the wrong size

For flutter_map, inspect widget constraints, the child's layout, and the alignment. Set explicit width and height when the child exceeds 30 pixels.

For Google Maps, check asset loading, BitmapDescriptor creation, render timing, and PNG encoding. Supplying both width and height fixes both dimensions; supplying one preserves aspect ratio.

For Advanced Markers, the README requires a mapId and markerType: GoogleMapMarkerType.advancedMarker. It also warns that PinConfig may not display on iOS, so use bitmaps there.

Alternatives to Adding Markers Directly in Flutter

Use native Google Maps markers through google_maps_flutter

This fits apps already committed to Google tiles, native map behavior, or Google-specific marker features. You get native integration and bitmap or Advanced Marker support. You give up direct widget composition and take on platform and package-version considerations.

On deprecation: legacy Marker is deprecated on web only, not across mobile. Verify against current docs.

Use flutter_map with a different tile provider

Choose this for provider flexibility, open-source composition, and widget markers. The trade-off is responsibility. You pick a reliable tile provider, meet its attribution and usage terms, and validate performance and feature support.

Pair Flutter rendering with an enterprise location platform

Logistics, fleet, and field-service apps often need routing, geocoding, and operational location data beyond pins. Flutter can stay the presentation layer while a platform such as NextBillion.ai supplies geospatial services.

NextBillion.ai services that commonly feed map markers include:

  • Live Tracking API returns last known asset locations and location history
  • Clustering API groups orders and jobs to minimize servicing distance (job allocation, not on-screen decluttering)
  • Maps API is powered by OpenStreetMap and TomTom data

You gain centralized location infrastructure and operational features. Trade-offs are integration effort and service dependency. NextBillion.ai lists a Flutter SDK among its resources, but confirm API compatibility with your chosen renderer. Its raster tiles suit flutter_map's raster TileLayer, though you still wire the tile integration yourself. Your app converts API responses into Marker objects itself.

Three Flutter map marker architecture alternatives comparison chart

Conclusion

Adding markers is straightforward once you choose the right package, validate coordinates, configure the provider, and use the rendering model that package supports. Reliable results depend on correct setup, stable state updates, sensible styling, and a plan for dense or fast-changing datasets.

Test across platforms, and check current package and provider documentation before you ship.

Frequently Asked Questions

What is a Flutter map?

It's an interactive map rendered inside a Flutter app. Common packages include flutter_map, which supports any tile provider, and google_maps_flutter, which renders Google Maps.

Is the Google Maps marker deprecated in Flutter?

Not broadly. The legacy Marker is deprecated on web, while AdvancedMarker is available and requires a map ID. Check the current google_maps_flutter documentation for your platform.

How do I add a marker to a Flutter map?

Prepare valid coordinates, create the package's marker object or widget, and add it to the marker layer or collection. Update state when data changes.

How do I use a custom widget as a marker in Flutter?

flutter_map renders a widget child directly. Google Maps generally needs the widget captured as PNG bytes and passed to BitmapDescriptor.bytes.

Why is my Flutter map marker not showing?

Common causes are invalid or reversed coordinates, a missing marker layer or state update, wrong package configuration, offscreen positions, and failed icon loading.

Can I add multiple markers or cluster them in Flutter?

Yes. Store markers in a collection. For dense datasets, use clustering, viewport filtering, or aggregation.