Skip to main content
Journey’s Navigation SDK provides a built-in user interface to display turn-by-turn instructions, manage spoken guidance messages, and display overall route information. The TomTomMap class provides a builder property that you can provide the built-in UI to be rendered on top of the map:
class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return TomTomMap(
      onPlatformViewCreated: (MapManager mapManager) async {
        await TomTomNavigationManager.instance.registerMap(mapManager);
      },
      // 👇 native TomTom navigation UI for showing turn-by-turn instructions
      navigationUIBuilder: (context, mapManager) {
        return TomTomFlutterNavigationUINative(mapManager: mapManager);
      },
    );
  }
}
Currently, the TomTomFlutterNavigationUINative will automatically display a platform view with TomTom’s native UI when a navigation session begins. The user can manually stop an active navigation session via the UI. To be notified when such event occurs, use the onNavigationStopped property:
class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return TomTomMap(
      navigationUIBuilder: (context, mapManager) {
        return TomTomFlutterNavigationUINative(
          mapManager: mapManager,
          onNavigationStopped: () {
            // called when navigation has stopped via user action
          },
        );
      },
    );
  }
}
This method is only called when UI events stop the active navigation session, and not programatically elsewhere in your codebase.

Customizing UI actions

The TomTomFlutterNavigationUINative widget provides callbacks you can use to override the widget’s default behavior on various actions, such as when the user mutes the active guidance messages or touches the active lane guidance banner. To customize the behavior for each action, you can provide your custom implementation:
final _navigationManager = TomTomNavigationManager.instance;
final _uiManager = TomTomFlutterNavigationUIManager.instance;

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

  @override
  Widget build(BuildContext context) {
    return TomTomMap(
      navigationUIBuilder: (context, mapManager) {
        return TomTomFlutterNavigationUINative(
          mapManager: mapManager,
          onArrivalAction: () async {
            // user touched "finalize" upon arrival in its final destination
            await _navigationManager.stopNavigation();
          },
          onConfirmationAction: (bool confirmed) async {
            // user confirmed if navigation should be cancelled or not
            if (confirmed) {
                await _navigationManager.stopNavigation();
            }
          },
          onSoundAction: (bool muted) async {
            // user touched mute/unmute button
            await _uiManager.muteTextToSpeech(mute: !muted);
          },
          onLanesAction: () async {
            // user touched lanes icons when displayed
            await _uiManager.hideLanes();
          },
          onThenAction: () async {
            // user touched "then" instruction banner
            await _uiManager.hideCombinedInstruction();
          },
          onSizeChanged: ({
            required double height,
            required double width,
          }) async {
            // the navigation UI height or width has changed
            await _mapManager.setContentInsets(
              MapManagerSetContentInsetsArguments(
                top: 0,
                leading: 0,
                bottom: height,
                trailing: 0,
              ),
            );
          },
        );
      },
    );
  }
}