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

Add a Polyline in Flutter ​

This tutorial shows how to draw polylines (lines connecting multiple points) on your MapMetrics Flutter map. Polylines are useful for showing routes, paths, or borders.

Prerequisites ​

Before you begin, ensure you have:

Basic Polyline ​

Draw a simple polyline with a PolylineLayer. Its geometry comes from a LineString, whose coordinates are a list of Position(lng, lat) — longitude first:

dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';

class PolylineExampleScreen extends StatefulWidget {
  const PolylineExampleScreen({super.key});

  @override
  State<PolylineExampleScreen> createState() => _PolylineExampleScreenState();
}

class _PolylineExampleScreenState extends State<PolylineExampleScreen> {
  MapController? mapController;

  final _routeLines = <LineString>[
    LineString(
      coordinates: [
        Position(2.3398, 48.8589),
        Position(2.3491, 48.8566),
        Position(2.3539, 48.8547),
        Position(2.3610, 48.8519),
        Position(2.3589, 48.8483),
        Position(2.3505, 48.8516),
        Position(2.3434, 48.8540),
        Position(2.3386, 48.8573),
        Position(2.3344, 48.8579),
        Position(2.3399, 48.8590),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Polyline Example')),
      body: MapMetricsView(
        options: MapOptions(
          initStyle:
              'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
          initCenter: Position(2.3470, 48.8540),
          initZoom: 14,
        ),
        onMapCreated: (controller) => mapController = controller,
        layers: [
          PolylineLayer(polylines: _routeLines, color: Colors.red, width: 4),
        ],
      ),
    );
  }
}

Styled Polylines ​

PolylineLayer supports color, width, gapWidth, blur, and dashArray (the lengths of alternating dashes and gaps, scaled by the line width). There is no separate dot/dash "pattern" type — everything is expressed through dashArray:

dart
// Solid thick line
final thickLine = PolylineLayer(
  polylines: [
    LineString(
      coordinates: [
        Position(2.330, 48.860),
        Position(2.345, 48.855),
        Position(2.360, 48.850),
      ],
    ),
  ],
  color: Colors.blue,
  width: 6,
);

// Dashed line
final dashedLine = PolylineLayer(
  polylines: [
    LineString(
      coordinates: [
        Position(2.330, 48.856),
        Position(2.345, 48.851),
        Position(2.360, 48.846),
      ],
    ),
  ],
  color: Colors.green,
  width: 3,
  dashArray: [4, 2],
);

Each PolylineLayer applies one color/width/dashArray combination to every LineString it holds — to mix styles (solid, dashed, thick), add each style as its own PolylineLayer in the layers: list rather than trying to style individual lines within a single layer.

Multiple Routes ​

Show several routes with different colors by stacking multiple PolylineLayers, and mark the cities along the way with a WidgetLayer:

dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';

class MultipleRoutesScreen extends StatefulWidget {
  const MultipleRoutesScreen({super.key});

  @override
  State<MultipleRoutesScreen> createState() => _MultipleRoutesScreenState();
}

class _MultipleRoutesScreenState extends State<MultipleRoutesScreen> {
  MapController? mapController;

  // Route 1: New York -> Philadelphia -> Washington DC
  final _eastCoast = LineString(
    coordinates: [
      Position(-74.0060, 40.7128), // New York
      Position(-75.1652, 39.9526), // Philadelphia
      Position(-77.0369, 38.9072), // Washington DC
    ],
  );

  // Route 2: Los Angeles -> Las Vegas -> Phoenix
  final _southwest = LineString(
    coordinates: [
      Position(-118.2437, 34.0522), // Los Angeles
      Position(-115.1398, 36.1699), // Las Vegas
      Position(-112.0740, 33.4484), // Phoenix
    ],
  );

  final _cities = const {
    'New York': Position(-74.0060, 40.7128),
    'Philadelphia': Position(-75.1652, 39.9526),
    'Washington DC': Position(-77.0369, 38.9072),
    'Los Angeles': Position(-118.2437, 34.0522),
    'Las Vegas': Position(-115.1398, 36.1699),
    'Phoenix': Position(-112.0740, 33.4484),
  };

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Multiple Routes')),
      body: MapMetricsView(
        options: MapOptions(
          initStyle:
              'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/YOUR_STYLE.json&token=YOUR_API_KEY',
          initCenter: Position(-95.7129, 37.0902), // Center of USA
          initZoom: 4,
        ),
        onMapCreated: (controller) => mapController = controller,
        layers: [
          PolylineLayer(polylines: [_eastCoast], color: Colors.blue, width: 4),
          PolylineLayer(polylines: [_southwest], color: Colors.red, width: 4),
        ],
        mapChildren: [
          WidgetLayer(
            markers: _cities.entries
                .map(
                  (e) => Marker(
                    point: e.value,
                    size: const Size(90, 28),
                    alignment: Alignment.bottomCenter,
                    child: Container(
                      padding:
                          const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(6),
                        boxShadow: const [
                          BoxShadow(color: Colors.black26, blurRadius: 4),
                        ],
                      ),
                      child: Text(
                        e.key,
                        style: const TextStyle(fontSize: 11),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),
                )
                .toList(),
          ),
        ],
      ),
    );
  }
}

Polyline Properties ​

PropertyTypeDescription
polylinesList<LineString>The line geometries to draw, LineString(coordinates: [Position(lng, lat), ...])
colorColorLine color (default: black)
widthintLine width in pixels (default: 1)
gapWidthintGap between the line and its casing, in pixels
blurintBlur applied to the line, in pixels
dashArrayList<int>?Alternating dash/gap lengths, scaled by width

Next Steps ​


Tip: Combine polylines with WidgetLayer markers at key points to create an interactive route map. Remember that Position is longitude-first (Position(lng, lat)) — the opposite order from the lat, lng convention used by many other map SDKs.