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.