Multiple Geometries in Flutter
This tutorial shows how to display markers, polylines, polygons, and circles all on the same map.
Prerequisites
Before you begin, ensure you have:
- Completed the Flutter Setup Guide
- A MapMetrics API key and style URL from the MapMetrics Portal
Complete Example
Display all geometry types together on a single map:
dart
import 'package:flutter/material.dart';
import 'package:mapmetrics/mapmetrics.dart';
class MultipleGeometriesScreen extends StatefulWidget {
@override
_MultipleGeometriesScreenState createState() => _MultipleGeometriesScreenState();
}
class _MultipleGeometriesScreenState extends State<MultipleGeometriesScreen> {
MapMetricsController? mapController;
bool showMarkers = true;
bool showPolylines = true;
bool showPolygons = true;
bool showCircles = true;
// --- Markers ---
final Set<Marker> markers = {
Marker(
markerId: MarkerId('eiffel'),
position: LatLng(48.8584, 2.2945),
infoWindow: InfoWindow(title: 'Eiffel Tower'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
),
Marker(
markerId: MarkerId('louvre'),
position: LatLng(48.8606, 2.3376),
infoWindow: InfoWindow(title: 'Louvre Museum'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
),
Marker(
markerId: MarkerId('notre_dame'),
position: LatLng(48.8530, 2.3499),
infoWindow: InfoWindow(title: 'Notre-Dame'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
),
Marker(
markerId: MarkerId('sacre_coeur'),
position: LatLng(48.8867, 2.3431),
infoWindow: InfoWindow(title: 'Sacré-Cœur'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueOrange),
),
};
// --- Polylines ---
final Set<Polyline> polylines = {
Polyline(
polylineId: PolylineId('walking_route'),
points: [
LatLng(48.8584, 2.2945), // Eiffel Tower
LatLng(48.8606, 2.3376), // Louvre
LatLng(48.8530, 2.3499), // Notre-Dame
],
color: Colors.blue,
width: 3,
),
Polyline(
polylineId: PolylineId('metro_line'),
points: [
LatLng(48.8530, 2.3499), // Notre-Dame
LatLng(48.8670, 2.3640), // Midpoint
LatLng(48.8867, 2.3431), // Sacré-Cœur
],
color: Colors.purple,
width: 3,
patterns: [PatternItem.dash(15), PatternItem.gap(10)],
),
};
// --- Polygons ---
final Set<Polygon> polygons = {
Polygon(
polygonId: PolygonId('latin_quarter'),
points: [
LatLng(48.855, 2.340),
LatLng(48.855, 2.360),
LatLng(48.845, 2.360),
LatLng(48.845, 2.340),
],
strokeWidth: 2,
strokeColor: Colors.green,
fillColor: Colors.green.withOpacity(0.15),
),
Polygon(
polygonId: PolygonId('marais'),
points: [
LatLng(48.862, 2.350),
LatLng(48.862, 2.370),
LatLng(48.852, 2.370),
LatLng(48.852, 2.350),
],
strokeWidth: 2,
strokeColor: Colors.orange,
fillColor: Colors.orange.withOpacity(0.15),
),
};
// --- Circles ---
final Set<Circle> circles = {
Circle(
circleId: CircleId('eiffel_area'),
center: LatLng(48.8584, 2.2945),
radius: 500,
strokeWidth: 2,
strokeColor: Colors.red,
fillColor: Colors.red.withOpacity(0.1),
),
Circle(
circleId: CircleId('sacre_coeur_area'),
center: LatLng(48.8867, 2.3431),
radius: 400,
strokeWidth: 2,
strokeColor: Colors.orange,
fillColor: Colors.orange.withOpacity(0.1),
),
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Multiple Geometries')),
body: Column(
children: [
// Toggle buttons
Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.grey[100],
child: Row(
children: [
_toggleChip('Markers', showMarkers, (v) => setState(() => showMarkers = v)),
SizedBox(width: 4),
_toggleChip('Lines', showPolylines, (v) => setState(() => showPolylines = v)),
SizedBox(width: 4),
_toggleChip('Polygons', showPolygons, (v) => setState(() => showPolygons = v)),
SizedBox(width: 4),
_toggleChip('Circles', showCircles, (v) => setState(() => showCircles = v)),
],
),
),
// Map
Expanded(
child: MapMetrics(
styleUrl: 'https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY',
onMapCreated: (controller) => mapController = controller,
initialCameraPosition: CameraPosition(
target: LatLng(48.8600, 2.3300),
zoom: 13.0,
),
markers: showMarkers ? markers : {},
polylines: showPolylines ? polylines : {},
polygons: showPolygons ? polygons : {},
circles: showCircles ? circles : {},
),
),
],
),
);
}
Widget _toggleChip(String label, bool value, ValueChanged<bool> onChanged) {
return FilterChip(
label: Text(label, style: TextStyle(fontSize: 12)),
selected: value,
onSelected: onChanged,
selectedColor: Colors.blue[100],
checkmarkColor: Colors.blue,
visualDensity: VisualDensity.compact,
);
}
}Geometry Types Summary
| Type | Widget | Key Properties |
|---|---|---|
| Marker | Marker | position, icon, infoWindow, draggable |
| Polyline | Polyline | points, color, width, patterns |
| Polygon | Polygon | points, strokeColor, fillColor, strokeWidth |
| Circle | Circle | center, radius, strokeColor, fillColor |
Next Steps
- Add a Polyline — Detailed polyline guide
- Add a Polygon — Detailed polygon guide
- Draw a Circle — Detailed circle guide
- Markers and Annotations — Detailed markers guide
Tip: Use FilterChip or ChoiceChip widgets to let users toggle individual geometry layers on and off. Pass an empty Set to hide a layer without removing the data.