Route line
The Navigation SDK allows you to display route lines on a map. This is a common UI component used in turn-by-turn navigation applications. While the route line is technically a line drawn on the map using the an API from the Mapbox Maps SDK, the Navigation SDK's route line API saves development time by addressing the most common navigation related use cases while also offering a high level of customization.
With the route line API you can manage the visual state of the route in the UI of your application.
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 theMapboxRouteLineApi
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 routeLineOptions = MapboxRouteLineOptions.Builder().build()
val routeLineApi = MapboxRouteLineApi(routeLineOptions)
val routeLineView = MapboxRouteLineView(routeLineOptions)
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.
One way to draw a route line is using a NavigationRouterCallback
when requesting a route via the MapboxNavigation
class.
private val routerCallback = object : NavigationRouterCallback {
override fun onRoutesReady(routes: List<NavigationRoute>, routerOrigin: RouterOrigin) {
// note: the first route in the list is considered the primary route
routeLineApi.setNavigationRoutes(routes) { value ->
routeLineView.renderRouteDrawData(mapStyle, value)
}
}
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
}
override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
}
}
Another way to draw a route line is by registering a RoutesObserver
with MapboxNavigation
:
private val routesObserver = object : RoutesObserver {
override fun onRoutesChanged(result: RoutesUpdatedResult) {
val routeLines = result.navigationRoutes.map { NavigationRouteLine(it, null) }
routeLineApi.setNavigationRouteLines(routeLines) { value ->
routeLineView.renderRouteDrawData(mapStyle, value)
}
}
}
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
at a minimum. 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
)
)
.accessToken(getMapboxAccessTokenFromResources())
.coordinates(listOf(origin, destination))
.build()
mapboxNavigation.requestRoutes(routeOptions,routesReqCallback)
To display alternative route lines, include the alternatives(true)
route option.
val routeOptions = RouteOptions.builder()
.alternatives(true)
.accessToken(getMapboxAccessTokenFromResources())
.coordinates(listOf(origin, destination))
.build()
mapboxNavigation.requestRoutes(routeOptions,routesReqCallback)
Handle route updates
When the navigation route changes, the MapboxRouteLineApi
must be updated with the latest route data and the changes rendered so that the route line displayed on the map is the current route.
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 route traveled
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 MapboxRouteLineOptions
. The color can be configured with RouteLineColorResources::routeLineTraveledColor
.
val routeLineOptions = MapboxRouteLineOptions()
.withVanishingRouteLineEnabled(true)
.build()
You should also register an OnIndicatorPositionChangedListener
with the map location component.
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()
.
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 three 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 is not always 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 MapboxRouteLineOptions
. The route line layers will be placed below the layer with the ID indicated in the routeLineBelowLayerId
option.
val routeLineOptions = MapboxRouteLineOptions.Builder()
.withRouteLineBelowLayerId("road-label")
.build()
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.Change the style of the route line
The RouteLineResources
class offers several options for customizing the style of the route line.