LogoLogo
CMSGitHubSupportBook a demo
  • Documentation
  • Academy
  • Help Center
  • Welcome
  • SDKS & Frameworks
    • Web
      • Getting Started
        • Prerequisites
          • MapsIndoors
          • Map Engine Provider
            • Option 1: Get your Mapbox Access Token
            • Option 2: Get your Google Maps API Keys​
          • Map Engine Setup
        • Getting Started: MapsIndoors
      • Map Visualization
        • Highlight, Hover and Select
        • Remove Labels from Buildings and Venues
        • Change Building Outline
        • Managing Collisions Based on Zoom Level
        • 3D Maps
          • Managing your 3D Maps
        • Base Map Styling - Google Maps
        • Managing feature visibility for Mapbox
      • Wayfinding
        • Directions
        • Directions Service
          • Tailoring the directions to your specific needs
        • Directions Renderer
          • Customizing the Route Animation
        • Multi-stop navigation
          • Custom Icons
        • User's Location as Point of Origin
      • Search
        • Search Operations
        • Searching
        • Using External ID, Geospatial Joins
        • Utilizing MapsIndoors Web Components and Other Searches
      • Map Management
      • Data Visualization
        • Display Heatmap Overlay
      • Other guides
        • Authentication
          • Single Sign-On
            • SSO Configuration
            • SSO Authorisation
          • 2-Factor Authentication
          • Password Reset
        • Application User Roles
        • Custom Properties
        • Display Language
        • Language
        • User Positioning
          • Show User's Location aka. Blue Dot
          • Using Cisco DNA Spaces
        • Working with Events
        • Turn Off Collisions Based on Zoom Level
        • Remove Labels from Buildings and Venues for Web
        • Synchronizing data for a subset of venues
        • Custom Floor Selector
      • Display Rules in Practice
      • Offline Data
      • Managing map visibility
    • Android
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
        • Enable Live Data
        • Integrating MapsIndoors into your own App
        • Migrating from V3 to V4
          • Migrating to Mapbox V11
      • Directions
        • Directions Service
        • Directions Renderer
          • User's Location as Point of Origin
        • Wayfinding Instructions
          • See Route Element Details
        • Using multi-stop navigation
      • Searching
        • Searching on a Map
        • Creating a Search Experience
      • Switching Solutions
      • Caching & Offline Data
      • Display Language
      • Displaying Objects
        • Application User Roles
        • Getting a Polygon from a Location
        • Location Clustering
        • Location Data Sources
        • Location Details
        • Turn Off Collisions Based on Zoom Level
        • Enabling and Disabling features on the map
      • Change Building Outline Color
      • Event Logging
      • Configuring a menu with AppConfig
      • Display Heatmap Overlay
      • Custom Properties
      • Custom Floor Selector
      • External IDs
      • User Positioning
        • Show User's Location aka. Blue Dot
        • Using Cisco DNA Spaces
        • Using Google Fused Location Provider
        • Using Indoor Atlas
      • Authentication
        • Single Sign-On
          • SSO Configuration
          • SSO Authorisation
        • 2-Factor Authentication
        • Password Reset
      • Display Rules in Practice
        • Label styling through Display Rules
      • Highlight and Select
    • iOS
      • Getting Started
        • Prerequisites
        • Set Up Your Environment
        • Display a Map
        • Search
        • Getting Directions
        • Migrating from v3 to v4
      • Directions
        • Directions Renderer
          • User's Location as Point of Origin
        • Wayfinding Instructions
          • See Route Element Details
        • Directions Service
        • Using multi-stop navigation
      • Searching
        • Searching on a Map
        • Creating a Search Experience
      • Caching & Offline Data
      • Displaying Objects
        • Application User Roles
        • Getting a Polygon from a Location
        • Location Details
        • Turn Off Collisions Based on Zoom Level
        • Enabling and Disabling features on the map
      • Custom Floor Selector
      • Change Building Outline Color
      • Custom Map Padding
      • Custom Properties
      • Display Rules in Practice
        • Label styling through Display Rules
      • Switching Solutions
      • Show User's Location aka. Blue Dot
        • Using Indoor Atlas
        • Using Cisco DNA Spaces
      • Highlight and Select
      • Display Language
    • React Native
      • Getting Started
        • Prerequisites
        • Project Setup
        • Displaying a Map
        • Creating a Search Experience
        • Getting Directions
        • Enabling Live Data
      • Showing Blue Dot
    • Flutter
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
      • Migration Guide
    • Integration API
      • Integration API Access
        • Access with Swagger
        • Access with Postman
        • Access with Python
        • Client credentials flow
      • Data Description
      • Reverse Geocoding
      • Route Access
      • OpenAPI Specification
    • Built-In Map Edits
      • Getting started
      • Authentication
      • Release notes
      • Reference docs
  • Products
    • Product Overview
    • CMS
      • Interface Overview
      • Display Rules
      • Media Library
        • 2D Models and Icons
        • 3D Models
      • Editing Data
      • Solution Settings
      • Settings
      • Data Concepts
      • User Roles
      • Route Network
        • Barrier Route Element
        • Door Route Element
      • Additional Location Details
    • Map Template
      • Getting Started
        • Web Component
        • React Component
      • Configuration
        • Query Parameters
      • Customization
      • Deploying Map Template to a cloud storage provider
      • 2D/3D Visibility Switch
      • External customization of the Map Template
      • Location Details configuration
      • Kiosk
        • QR code configuration
  • Other
    • Design
      • Standard MapsIndoors Map Style
      • Using a Custom Mapbox MapStyle
    • Changelog
      • Web SDK
        • V4
        • V3
      • Android SDK
        • V4
        • V3
      • iOS SDK
        • V4
        • V3
      • React Native SDK
      • Flutter SDK
      • MI Components
      • Map Template
    • Glossary
  • Legacy Docs
    • Android SDK V3
      • Getting Started
        • Prerequisites
        • Create a New Project
        • Show a Map
        • Create a Search Experience
        • Getting Directions
        • Enable Live Data
        • Integrating MapsIndoors into your own App
    • iOS SDK V3
      • Getting Started
        • Prerequisites
        • Set Up Your Environment
        • Display a Map
        • Search
        • Directions
        • Live Data
        • Integrating MapsIndoors into your own App
      • Inspect Route Element for iOS v3
      • Using Cisco DNA Spaces
      • Using Indoor Atlas
      • Switching Solutions
      • Show User's Location aka. Blue Dot
      • Application User Roles
      • Getting a Polygon from a Location
      • Location Details
  • MapsIndoors SDK Firewall
  • Google Analytics & Logging
  • Reference Docs
    • Web SDK
    • Android SDK
    • iOS SDK
    • React Native SDK
    • Flutter SDK
Powered by GitBook
On this page
  • Get Directions Between Two Locations​
  • Change Transportation Mode​

Was this helpful?

Export as PDF
  1. SDKS & Frameworks
  2. Flutter
  3. Getting Started

Getting Directions

Last updated 2 days ago

Was this helpful?

Now we have a simple map where you can search for locations. When finishing this step you'll be able to create a route with directions between two points and change the transportation mode.

Get Directions Between Two Locations

After having created our list of search results, we have a good starting point for creating directions between two Locations. Since our search only supports searching for a single location, we will hardcode a Location's coordinate into our app, and use that as the basis for our Origin. Then we'll create a route, show the navigation details, and display the route on the map.

We have already created a point in the basic example, called _userPosition to use as a starting point for directions on MapState. The position given with the example is for the main entrance to the White House, replace it with some location that fits your usecase.

final _userPosition = MPPoint.withCoordinates(
    longitude: -97.74182,
    latitude: 30.3607287,
    floorIndex: 30);

We can extend the search functionality we made earlier by implementing the listener on the , and showing the selected location's details on the bottom sheet:

void onMapControlReady(MPError? error) async {
  if (error == null) {
    ...
    // Add a listener for location selection events, we do not want to stop the SDK from moving the camera, so we do not comsume the event
    _mapControl
      ..setOnLocationSelectedListener(onLocationSelected, false)
      ..goTo(await getDefaultVenue());
  } else {
    ...
  }
}

and implementing the onLocationSelected listener:

void onLocationSelected(MPLocation? location) {
  // if no location is selected, close the sheet
  if (location == null) {
    _controller?.close();
    _controller = null;
    return;
  }
  // show location details
  _controller = _scaffoldKey.currentState?.showBottomSheet((context) {
    return Container(
      color: Colors.white,
      padding: const EdgeInsets.only(bottom: 50.0, left: 100, right: 100),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const SizedBox(
            height: 30,
          ),
          Text(location.name),
          const SizedBox(
            height: 30,
          ),
          Text("Description: ${location.description}"),
          const SizedBox(
            height: 30,
          ),
          Text("Building: ${location.buildingName} - ${location.floorName}"),
          const SizedBox(
            height: 30,
          ),
          ...
        ],
      ),
    );
  });
  _controller?.closed.then((value) => _mapControl.selectLocation(null));
}

Now we will create a class that takes a origin and destination and can handle the controls of a route. This is a rather complex class that creates a route, lets us traverse it without errors and displays the steps of the route in the bottom sheet. A minimal example would only require the constructor, the leg selected listener and the UI.

class RouteHandler {
  RouteHandler(
      {required MPPoint origin,
      required MPPoint destination,
      required ScaffoldState scaffold}) {
    _service.getRoute(origin: origin, destination: destination).then((route) {
      _route = route;
      _renderer.setRoute(route);
      // Start some UI handling here later
    });
  }
  final _service = MPDirectionsService();
  final _renderer = MPDirectionsRenderer();
  late final MPRoute _route;
}
class RouteHandler {
  RouteHandler(
      {required MPPoint origin,
      required MPPoint destination,
      required ScaffoldState scaffold}) {
    _service.getRoute(origin: origin, destination: destination).then((route) {
      ...
      _renderer.setOnLegSelectedListener(onLegSelected);
      // Start some UI handling here later
    });
  }

  ...

  // backing field for the current route leg index
  int _currentIndex = 0;

  int get currentIndex {
    return _currentIndex;
  }

  // clamp the index to be in the correct range
  set currentIndex(int index) {
    _currentIndex = index.clamp(0, _route.legs!.length - 1);
  }

  // updates the state of the routehandler if the route is updated externally, eg. by tapping the next marker on the route
  void onLegSelected(int legIndex) {
    _controller?.setState!(() => currentIndex = legIndex);
  }

  // external handle to clear the route
  void removeRoute() {
    _renderer.clear();
  }
}

Finally we want some UI interaction, so we add a ShowRoute method that creates a BottomSheet which contains some navigation icons, to move between legs of the route, and a text field to display the steps of the current leg. We also add a method to expand the route steps in a way that we can show the leg in a single string.

Then we call showRoute from our constructor. Additionally we close the BottomSheet when removing the map.

class RouteHandler {
  RouteHandler(
      {required MPPoint origin,
      required MPPoint destination,
      required ScaffoldState scaffold}) {
    _service.setTravelMode(MPDirectionsService.travelModeDriving);
    _service.getRoute(origin: origin, destination: destination).then((route) {
      ...
      showRoute(scaffold);
    });
  }
  PersistentBottomSheetController? _controller;

  ...

  // opens the route on a bottom sheet
  void showRoute(ScaffoldState scaffold) {
    _controller = scaffold.showBottomSheet((context) {
      return Container(
        color: Colors.white,
        padding: const EdgeInsets.only(top: 50.0, bottom: 50.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: [
            // goes a step back on the route
            IconButton(
              onPressed: () async {
                currentIndex--;
                await _renderer.selectLegIndex(currentIndex);
              },
              icon: const Icon(Icons.keyboard_arrow_left),
              iconSize: 50,
            ),
            // displays the route instructions
            Expanded(
              child: Text(
                expandRouteSteps(_route.legs![currentIndex].steps!),
                softWrap: true,
                textAlign: TextAlign.center,
              ),
            ),
            // goes a step forward on the route
            IconButton(
              onPressed: () async {
                currentIndex++;
                await _renderer.selectLegIndex(currentIndex);
              },
              icon: const Icon(Icons.keyboard_arrow_right),
              iconSize: 50,
            ),
          ],
        ),
      );
    });
    // if the bottom sheet is closed, then clear the route
    _controller?.closed.then((val) {
      _renderer.clear();
    });
  }

  // external handle to clear the route
  void removeRoute() {
    _renderer.clear();
    _controller?.close();
  }

  // expands the step instructions into a single string for the entire leg
  String expandRouteSteps(List<MPRouteStep> steps) {
    String sum = "${steps[0].maneuver}";
    for (final step in steps.skip(1)) {
      sum += ", ${step.maneuver}";
    }
    return sum;
  }
}

We can now add a button on our onLocationSelected bottomsheet to generate a route from _userPosition to the selected location:

final _scaffoldKey = GlobalKey<ScaffoldState>();
RouteHandler? _routeHandler;
PersistentBottomSheetController? _controller;

void onLocationSelected(MPLocation? location) {
  ...
  // if an active route is displayed, remove it from view
  _routeHandler?.removeRoute();
  // show location details
  _controller = _scaffoldKey.currentState?.showBottomSheet((context) {
    return Container(
      ...
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          ...
          // when clicked will create a route from the user position to the location
          ElevatedButton(
            onPressed: () => _routeHandler = RouteHandler(
                origin: _userPosition,
                destination: location.point,
                scaffold: _scaffoldKey.currentState!),
            child: const Row(
              children: [
                Icon(Icons.keyboard_arrow_left_rounded),
                SizedBox(
                  width: 5,
                ),
                Text("directions")
              ],
            ),
          ),
        ],
      ),
    );
  });
  _controller?.closed.then((value) => _mapControl.selectLocation(null));
}

We can now show and navigate a route from our _userPosition to a selected location.

In MapsIndoors, the transportation mode is referred to as travel mode. There are four travel modes, walking, bicycling, driving and transit (public transportation). The travel modes generally applies for outdoor navigation. Indoor navigation calculations are based on walking travel mode.

To swap Travel Modes you set the Travel Mode before making a query for the route:

RouteHandler(
    {required MPPoint origin,
    required MPPoint destination,
    required ScaffoldState scaffold}) {
  _service.setTravelMode(MPDirectionsService.travelModeDriving);
  _service.getRoute(origin: origin, destination: destination).then((route) {
    _route = route;
    _renderer.setRoute(route);
    _renderer.setOnLegSelectedListener(onLegSelected);
    showRoute(scaffold);
  });
}

Expected result:

First lets set up the constructor and services, we want to create the RouteHandler with an origin, destination and the state of our Scaffold (to create a bottom sheet later). We will also set up our and and generate a route immediately. finally we show the route on the Renderer.

Now we want some controllers for the state of our route, we want a method to safely update the leg index, we want to listen to when the leg index changes and we want to be able to remove the route again. First we add a to the class and set it on the renderer. Then we add a getter/setter for the current leg index, where we ensure that we cannot get an index that is out of bounds for the current route. and finally we add a removeRoute method that clears the route from the map.

With this we now have a class that will handle creating a Route and displaying it on the map for us. You can see the entire implementation of RouteHandler here:

Change Transportation Mode

The accompanying UI and implementation of this directions experience can be found in the getting started app sample.

​
onLocationSelected
MapsIndoorsWidget
MPDirectionsService
MPDirectionsRenderer
onLegSelectedListener
main.dart
​
Getting Started App sample