Skip to content

Basic Usage

Display your first Map

Import the maplibre package and use the MapLibreMap widget to display a map.

map_screen.dart
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import 'package:flutter/material.dart';

import 'package:maplibre/maplibre.dart';

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

  @override
  State createState() => FullMapState();
}

class MapScreenState extends State<MapScreen> {
  MapController? _mapController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MapLibreMap(
        onMapCreated: (controller) {
          // Store the map controller for later use. You can use it to control 
          // the map programmatically.
          _mapController = controller;
        },
        onStyleLoaded: (style) {
          // Add your sources and layers here or do any other setup after the 
          // style has been loaded.
          debugPrint('Map loaded 😎');
        },
      ),
    );
  }
}

The result should look something like this:

First map

If the map style isn't specified, the default MapLibre style is used. Read the Styles chapter to learn how to use other styles.

Programmatic Control

It is possible to update or change the MapLibreMap widget during its lifetime.

The MapLibreMap widget

The MapLibreMap is used to specify initial values. Parameters that don't begin with init* can be updated in a declarative way just like any other Flutter Widget. The most simple way is to use the MapLibreMap widget in a StatefulWidget and calling setState().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@immutable
class MyMapWidget extends StatefulWidget {
  const MyMapWidget({super.key});

  @override
  State<MyMapWidget> createState() => _MyMapWidget();
}

class _MyMapWidget extends State<GesturesPage> {
  // Using this field to store the widget state
  bool _gesturesEnabed = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MapLibreMap(
          options: MapOptions(
            // parameters that start with init* can't be updated
            initCenter: Geographic(lon: 9.17, lat: 47.68),
            initZoom: 3,
            // other parameters can be updated
            gestures: _gesturesEnabled
                ? MapGestures.all()
                : MapGestures.none(),
          ),
          onEvent: (event) {
            if (event case MapEventClick()) {
              // update the map widget using Flutters' state management
              setState() {
                _gesturesEnabed = !_gesturesEnabed;
              }
            }
          }
      ),
    );
  }
}

All parameters that start with init* can't be updated using this method and need to use the MapController or the StyleController.

The MapController

The MapController can be used by either using the onMapCreated callback or by listening in the onEvent callback for the MapEventMapCreated event type.

You can store the MapController in a field variable for later use.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class _MyMapWidget extends State<GesturesPage> {
  MapController? _mapController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MapLibreMap(
          options: MapOptions(initCenter: Geographic(lon: 9.17, lat: 47.68), initZoom: 3),
          onEvent: (event) {
            // check if the MapEvent type is a MapEventMapCreated
            if (event case MapEventMapCreated()) {
              // store the MapController for later use
              _mapController = event.mapController;
            }
          }
      ),
    );
  }
}

The StyleController

The StyleController is a construct to make style related operations on the map. It can be used either by listening to the MapEventStyleLoaded event or the onStyleLoaded callback.

After it has loaded you can access the StyleController at any time from the style getter of MapController.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class _MyMapWidget extends State<GesturesPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MapLibreMap(
          options: MapOptions(initCenter: Geographic(lon: 9.17, lat: 47.68), initZoom: 3),
          onEvent: (event) {
            // check if the MapEvent type is a MapEventStyleLoaded
            if (event case MapEventStyleLoaded()) {
              // This event gets emitted every time a style finishes loading.
              event.style.addSource(...);
              event.style.addLayer(...);
            }
          }
      ),
    );
  }
}

Another way to access the StyleController is by calling the style getter on the MapController. Modifications on the map style are only possible after the style has been loaded. In case it hasn't loaded, the getter returns null.

1
2
3
4
5
6
MapController? _mapController;

void doSomething() {
  // only adds the source if the style has finished loading and a source can be added.
  _mapController?.style?.addSource(...);
}