Skip to content

Dart / Flutter Quickstart

pubspec.yaml

yaml
dependencies:
  maplibre_gl: ^0.20.0
  http: ^1.2.0

Render a map

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

class MapScreen extends StatefulWidget {
  const MapScreen({super.key});
  @override
  State<MapScreen> createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  static const _key = String.fromEnvironment('MFD_PUB_KEY');
  late final String _styleUrl =
      'https://api.mapsfordevs.com/styles/standard.json?key=$_key';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: MapLibreMap(
        styleString: _styleUrl,
        initialCameraPosition: const CameraPosition(
          target: LatLng(-26.20, 28.04),
          zoom: 11,
        ),
      ),
    );
  }
}

Build with:

bash
flutter run --dart-define=MFD_PUB_KEY=mfd_pub_xxx

Geocoding

dart
import 'dart:convert';
import 'package:http/http.dart' as http;

class GeocodeItem {
  final double lat, lng, confidence;
  final String label, type;
  GeocodeItem.fromJson(Map<String, dynamic> j)
      : lat = (j['lat'] as num).toDouble(),
        lng = (j['lng'] as num).toDouble(),
        label = j['label'],
        confidence = (j['confidence'] as num).toDouble(),
        type = j['type'];
}

class MapsForDevs {
  final String apiKey;
  MapsForDevs(this.apiKey);

  Future<List<GeocodeItem>> geocode(String query, {String? country, int limit = 5}) async {
    final params = {'q': query, 'limit': '$limit'};
    if (country != null) params['country'] = country;
    final uri = Uri.https('api.mapsfordevs.com', '/geocode/forward', params);

    final resp = await http.get(uri, headers: {'Authorization': 'Bearer $apiKey'});
    final body = jsonDecode(resp.body) as Map<String, dynamic>;

    if (body['ok'] != true) throw Exception(body['error'] ?? 'mfd error');
    return (body['items'] as List).map((e) => GeocodeItem.fromJson(e)).toList();
  }
}

Switch language at runtime

dart
void setLanguage(MapLibreMapController c, String lang) {
  for (final layer in ['place_label', 'transportation_name', 'poi_label']) {
    c.setLayerProperties(layer, SymbolLayerProperties(
      textField: ['coalesce',
        ['get', 'name:$lang'],
        ['get', 'name:latin'],
        ['get', 'name']
      ],
    ));
  }
}

Cleanup

MapLibreMap disposes its controller automatically when the widget is removed. No manual cleanup needed in Flutter.