# Center Traffic

Last updated:

<!-- -->

October 18, 2026

<!-- -->

\| 4 minutes read

<br />

<br />

This example showcases how to build a Flutter app featuring an interactive map and how to center the camera on a route area with traffic, using the Maps SDK for Flutter.

## How it works[​](#how-it-works "Direct link to How it works")

The example app demonstrates the following features:

* Display an interactive map.
* Calculate a route.
* Center on a traffic segment.

![Initial screen](/docs/flutter/assets/images/example_flutter_center_traffic1-bf9cc971c225d7e91903f68f0710ddb3.png)

**Initial screen**

![Route calculated](/docs/flutter/assets/images/example_flutter_center_traffic2-e56138e05b05dfc0b192e58fcc42e41d.png)

**Route calculated**

![Map camera centered traffic](/docs/flutter/assets/images/example_flutter_center_traffic3-e63a70c561a85dbae481016e2d31b316.png)

**Map camera centered traffic**

### UI and Map Integration[​](#ui-and-map-integration "Direct link to UI and Map Integration")

The following code builds a UI with an interactive `GemMap` widget and an AppBar with buttons for computing a route, centering on traffic, and clearing the presented route.

main.dart[View on Github](https://github.com/magiclane/magiclane-maps-sdk-examples-for-flutter/tree/main/center_traffic/lib/main.dart?ref_type=heads#L10)

```dart
const projectApiToken = String.fromEnvironment('YOUR_API_TOKEN_HERE');
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Center Traffic',
      home: MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late GemMapController _mapController;

  // We use the handler to cancel the route calculation.
  TaskHandler? _routingHandler;

  Route? _route;

  @override
  void dispose() {
    GemKit.release();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.deepPurple[900],
        title: const Text(
          'Center Traffic',
          style: TextStyle(color: Colors.white),
        ),
        actions: [
          // Routes are not built.
          if (_routingHandler == null && _route == null)
            IconButton(
              onPressed: () => _onBuildRouteButtonPressed(context),
              icon: const Icon(Icons.route, color: Colors.white),
            ),
          // Routes calculating is in progress.
          if (_routingHandler != null)
            IconButton(
              onPressed: () => _onCancelRouteButtonPressed(),
              icon: const Icon(Icons.stop, color: Colors.white),
            ),
          // Routes calculating is finished.
          if (_route != null)
            IconButton(
              onPressed: () => _centerOnTraffic(_route!),
              icon: const Icon(Icons.center_focus_strong, color: Colors.white),
            ),
          if (_route != null)
            IconButton(
              onPressed: () => _onClearRoutesButtonPressed(),
              icon: const Icon(Icons.clear, color: Colors.white),
            ),
        ],
      ),
      body: GemMap(
        key: ValueKey("GemMap"),
        onMapCreated: _onMapCreated,
        appAuthorization: projectApiToken,
      ),
    );
  }

  // The callback for when map is ready to use.
  Future<void> _onMapCreated(GemMapController controller) async {
    // Save controller for further usage.
    _mapController = controller;
  }

  void _onBuildRouteButtonPressed(BuildContext context) {
    // Define the departure.
    final departureLandmark = Landmark.withLatLng(
      latitude: 48.85682,
      longitude: 2.34375,
    );

    // Define the destination.
    final destinationLandmark = Landmark.withLatLng(
      latitude: 50.84644,
      longitude: 4.34587,
    );

    // Define the route preferences.
    final routePreferences = RoutePreferences();

    _showSnackBar(context, message: "The route is being calculated.");

    // Calling the calculateRoute SDK method.
    // (err, results) - is a callback function that gets called when the route computing is finished.
    // err is an error enum, results is a list of routes.

    _routingHandler = RoutingService.calculateRoute(
      [departureLandmark, destinationLandmark],
      routePreferences,
      (err, routes) {
        // If the route calculation is finished, we don't have a progress listener anymore.
        _routingHandler = null;
        ScaffoldMessenger.of(context).clearSnackBars();

        // If there aren't any errors, we display the routes.
        if (err == GemError.success) {
          // Get the routes collection from map preferences.
          final routesMap = _mapController.preferences.routes;

          // Display the routes on map.
          routesMap.add(routes.first, true);

          // Center the camera on routes.
          _mapController.centerOnRoute(routes.first);
          setState(() {
            _route = routes.first;
          });
        }
      },
    );

    setState(() {});
  }

  void _centerOnTraffic(Route route) {
    // Get the traffic events from the route.
    final trafficEvents = route.trafficEvents;

    if (trafficEvents.isEmpty) {
      _showSnackBar(context, message: "No traffic events found.");
      return;
    }

    final trafficEvent = trafficEvents.first;

    _mapController.centerOnRouteTrafficEvent(trafficEvent, zoomLevel: 70);
  }

  void _onClearRoutesButtonPressed() {
    // Remove the routes from map.
    _mapController.preferences.routes.clear();
    // Remove the highlights from map.
    _mapController.deactivateAllHighlights();

    setState(() {
      _route = null;
    });
  }

  void _onCancelRouteButtonPressed() {
    // If we have a progress listener we cancel the route calculation.
    if (_routingHandler != null) {
      RoutingService.cancelRoute(_routingHandler!);

      setState(() {
        _routingHandler = null;
      });
    }
  }

  // Show a snackbar indicating that the route calculation is in progress.
  void _showSnackBar(
    BuildContext context, {
    required String message,
    Duration duration = const Duration(hours: 1),
  }) {
    final snackBar = SnackBar(content: Text(message), duration: duration);

    ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }
}


```
