Skip to main content

Route line

The Navigation SDK allows you to display route lines on a map, which is an integral component used in turn-by-turn navigation applications.

The interfaces described in this guide provide abstractions to prepare the navigation data and visualize it on a Mapbox Map.

Use the route line UI component

The route line UI component consists of two main classes:

  • The MapboxRouteLineApi has methods for creating and modifying the route line and producing data describing the view related mutations.
  • The MapboxRouteLineView handles consuming the data produced by the MapboxRouteLineApi and rendering the results on the map.

By default, the route line UI component displays the route as a solid blue line with a darker blue outline.

Instantiate the route line API

Instantiate the MapboxRouteLineApi and MapboxRouteLineView classes in your Activity or Fragment.

val routeLineApiOptions = MapboxRouteLineApiOptions.Builder().build()
val routeLineApi = MapboxRouteLineApi(routeLineApiOptions)

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder(context).build()
val routeLineView = MapboxRouteLineView(routeLineViewOptions)

Draw a route line by passing a NavigationRoute instance to the MapboxRouteLineApi and rendering the result with the MapboxRouteLineView. Read more about requesting a NavigationRoute in the Route generation guide.

A recommended way to draw route lines is by registering a RoutesObserver with MapboxNavigation:

private val routesObserver = object : RoutesObserver {
override fun onRoutesChanged(result: RoutesUpdatedResult) {
/*
obtain metadata to enhance visualization of alternative routes
and hide parts that overlap with the primary route
*/
val alternativesMetadata = mapboxNavigation.getAlternativeMetadataFor(
result.navigationRoutes
)
routeLineApi.setNavigationRoutes(
result.navigationRoutes,
alternativesMetadata,
) { value ->
routeLineView.renderRouteDrawData(mapStyle, value)
}
}
}

This approach ensures that whenever routes get updated the new information will be reflected on the route lines. This includes change in selected primary route, re-drawing routes after a reroute event, refreshes to update congestion information, or removal of invalid alternatives after the fork is passed.

Use alternatives metadata
Whenever updating the routes, make sure that you're providing the alternative metadata to enhance visualization of alternative routes and hide parts that overlap with the primary route.

Be sure to always unregister observers in onStop() or onDestroy().

Also don't forget to cancel any potential in-flight MapboxRouteLineApi requests and MapboxRouteLineView background tasks:

override fun onDestroy() {
super.onDestroy()
routeLineApi.cancel()
routeLineView.cancel()
}

Request routes with the right data

When requesting a route using MapboxNavigation there are some options that are necessary if you want to display traffic congestion on the route line. You can use RouteOptions.builder().applyDefaultNavigationOptions(), which will use the PROFILE_DRIVING_TRAFFIC profile and the required annotations.

If you are using custom route options, be sure to use the PROFILE_DRIVING_TRAFFIC profile and include at least ANNOTATION_CONGESTION_NUMERIC and ANNOTATION_DISTANCE in the annotationsList. If any of these options are absent, there will not be enough data in the directions response to display traffic congestion on the route line.

val routeOptions = RouteOptions.builder()
.profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
.annotationsList(
listOf(
DirectionsCriteria.ANNOTATION_CONGESTION_NUMERIC,
DirectionsCriteria.ANNOTATION_DISTANCE
)
)
.coordinates(listOf(origin, destination))
.build()

mapboxNavigation.requestRoutes(routeOptions, callback)

To display alternative route lines, include the alternatives(true) route option.

val routeOptions = RouteOptions.builder()
.alternatives(true)
.coordinates(listOf(origin, destination))
.build()

mapboxNavigation.requestRoutes(routeOptions, callback)

Handle progress along the route

When progress along the route changes, the MapboxRouteLineApi must be updated with the latest information to correctly render active route leg or already traveled route part.

Register a RouteProgressObserver with MapboxNavigation to keep the route line updated.

private val routeProgressObserver = RouteProgressObserver { routeProgress ->
routeLineApi.updateWithRouteProgress(routeProgress) { result ->
routeLineView.renderRouteLineUpdate(mapStyle, result)
}
}

Always be sure to unregister observers in onStop() or onDestroy().

Customize the route line

Differentiate the traveled route part

To visually differentiate the part of the route that has already been traveled from the route ahead, use the route line API's vanishing route line feature. Enabling this feature will make the section of the route line the behind the user's current location transparent by default, or you can configure a custom color.

Enable this feature using the MapboxRouteLineApiOptions. The color can be configured with RouteLineColorResources.routeLineTraveledColor.

val routeLineApiOptions = MapboxRouteLineApiOptions.Builder()
.vanishingRouteLineEnabled(true)
.build()

Then, register an OnIndicatorPositionChangedListener with the map location component to pass information about the current location of the user indicator on the map to the route line. This information is used to calculate the part of the route line that needs to be updated.

mapView.location.addOnIndicatorPositionChangedListener(onPositionChangedListener)
private val onPositionChangedListener = OnIndicatorPositionChangedListener { point ->
val result = routeLineApi.updateTraveledRouteLine(point)
routeLineView.renderRouteLineUpdate(mapStyle, result)
}

Always be sure to unregister observers in onStop() or onDestroy().

Requirements for the traveled route line visualization
To change the appearance of the traveled route part, the setting needs to be enabled in MapboxRouteLineApiOptions but also data from both the OnIndicatorPositionChangedListener and RouteProgressObserver (see Handle route updates) needs to be provided.

Position the route line relative to map layers

The map on which you are displaying your route line contains many individual layers (for example, roads, buildings, labels, and more). The route line UI component consists of multiple layers that are added to the map.

By default, the route line is placed on top of all the other layers in the map. This rarely the most optimal position for a route line because it may appear on top of road labels and other labels on the map.

You can specify the route line layers' vertical position within all map layers using the routeLineBelowLayerId parameter of MapboxRouteLineViewOptions. The route line layers will be placed below the layer with the ID indicated in the routeLineBelowLayerId option.

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder()
.routeLineBelowLayerId("road-label")
.build()
Which layer ID should I use?
For navigation-related Mapbox map styles, you can use a routeLineBelowLayerId value of "road-label", but this layer is not present in all map styles. If you are using a custom map style or another Mapbox-designed style, you can find the layer IDs that exist in the style by opening the style in Mapbox Studio or printing the style JSON to the console. For more information see Finding layer ids.
Compatibility with Mapbox Standard Style
When the route line component is used with the Mapbox Standard Style, the layers are added to the MIDDLE slot. Support for selecting the slot to which the route line should be inserted will be introduced in future releases.

Change the style of the route line

The MapboxRouteLineViewOptions class offers several options for customizing the style of the route line.

Color

You can customize the route line colors by providing RouteLineColorResources to the MapboxRouteLineViewOptions.Builder class.

val customColorResources = RouteLineColorResources.Builder()
.routeDefaultColor(Color.parseColor("#FFCC00"))
// ... etc
.build()

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder(this)
.routeLineColorResources(customColorResources)
.build()

Scale

A route line consists of multiple layers on the map. The lowest layer is called the casing layer. Above the casing layer is the main route line layer. And the top layer is a traffic line layer. By default, the casing layer has the greatest width giving the appearance of a border around the route line and traffic line.

The scaling behavior of these lines is determined by the Expression class from the Maps SDK. With the RouteLineResources.Builder you can customize the scaling expressions rather than using the defaults. See the Maps SDK documentation for more information on creating expressions.

val scaleExpressions = RouteLineScaleExpressions.Builder()
.routeCasingLineScaleExpression(customCasingExpression)
.routeLineScaleExpression(customRouteLineExpression)
.routeTrafficLineScaleExpression(customTrafficLineExpression)
.build()

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder(this)
.scaleExpressions(scaleExpressions)
.build()

Style inactive route legs

It's common to use routes with multiple waypoints. For better route visibility, you may want the route line to visually differentiate between the active route leg and inactive route legs.

When this feature is enabled and properly configured, the inactive route legs will appear a different color (or transparency) than the active route leg, making it clearer to the driver where the route is taking them. As the driver transitions from one route leg to another, the route leg colors will change to differentiate the active route leg from the inactive route legs. This feature only works on routes with multiple waypoints.

Enable this feature by setting the MapboxRouteLineApiOptions.styleInactiveRouteLegsIndependently option to true.

val routeLineApiOptions = MapboxRouteLineApiOptions.Builder()
.styleInactiveRouteLegsIndependently(true)
.build()

Set the colors used for inactive route legs using one of the options in the RouteLineColorResources class. There are multiple options to style inactive route legs. For example, you can use inActiveRouteLegsColor to set the default color of inactive route legs. Additionally, there are options to style congestion levels, restricted roads, or closures on inactive route legs.

val customColorResources = RouteLineColorResources.Builder()
.inActiveRouteLegsColor(Color.parseColor("#FFCC00"))
.build()
Requirements for styling inactive legs
To change the appearance of the inactive legs, the setting needs to be enabled in MapboxRouteLineApiOptions but also data from the RouteProgressObserver (see Handle route updates) needs to be provided.

Display restricted road sections

The MapboxRouteLineViewOptions class includes an option to display roads or sections of roads designated as restricted. When you set this option to true, the route line will display a dashed line.

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder(context)
.displayRestrictedRoadSections(true)
.build()

Further customization of the restricted road dashed line is available in the MapboxRouteLineViewOptions class. The available options are restrictedRoadDashArray, restrictedRoadOpacity and restrictedRoadLineWidth. These options are used when creating the layer that contains the restricted line and correspond to the dash line layer options of the Maps SDK. See the Maps SDK line layer documentation for further explanation of these options.

You can configure the color of the dashed line representing restricted roads using the RouteLineColorResources class to set the restrictedRoadColor and alternativeRouteRestrictedRoadColor options.

val customColorResources = RouteLineColorResources.Builder()
.restrictedRoadColor(Color.parseColor("#FFCC00"))
.alternativeRouteRestrictedRoadColor(Color.parseColor("#FFCC00"))
.build()

Display soft gradient for traffic

Traffic congestion is represented on the route line by different colors. By default there is an abrupt transition from one color to the next. The MapboxRouteLineViewOptions class includes an option to display a gradient transition between the colors instead.

There is also an option to influence the length of the gradient transition. A higher value will result in a gradient over a longer length. A smaller value will result in a gradient that is shorter in length. In general, the softGradientTransition option should be a value between 5.0 and 75.0.

val routeLineViewOptions = MapboxRouteLineViewOptions.Builder(context)
.displaySoftGradientForTraffic(true)
.softGradientTransition(30.0)
.build()

Update style at runtime

The route line UI component allows for changing a subset of MapboxRouteLineViewOptions at runtime without recreating MapboxRouteLineView or MapboxRouteLineApi. The specific options that can be changed dynamically are defined in the MapboxRouteLineViewDynamicOptionsBuilder class.

routeLineView.updateDynamicOptions(style) {
routeLineColorResources(newColors)
// ...
}
routeLineApi.getRouteDrawData {
routeLineView.renderRouteDrawData(style, it)
}
Was this page helpful?