Route callouts
The Navigation SDK allows you to display callouts on a map that represent the duration of the route(s) and customize the style of the callouts. This is a common UI component used in turn-by-turn navigation applications.
Enable the route callout feature
The route callout components are integrated into two main classes:
- The
MapboxRouteLineApi
generates callouts for routes. - The
MapboxRouteLineView
class handles consuming the calculated callout data and rendering it on the map.
Following this guide instantiate MapboxRouteLineApi
with the MapboxRouteLineApiOptions.isRouteCalloutsEnabled
set to true
val options = MapboxRouteLineApiOptions.Builder()
.isRouteCalloutsEnabled(true)
.build()
val routeLineApi = MapboxRouteLineApi(options)
Then you need to enable it in MapboxRouteLineView
by calling the setCalloutAdapter
function
providing an instance of ViewAnnotationManager
and an implementation of MapboxRouteCalloutAdapter
.
The SDK provides the default implementation of this adapter DefaultRouteCalloutAdapter
so you can start using it until you need more customized UI or behavior.
val routeLineOptions = MapboxRouteLineViewOptions.Builder(context).build()
val routeLineView = MapboxRouteLineView(routeLineOptions)
val viewAnnotationManager: ViewAnnotationManager = mapView.viewAnnotationManager
val defaultAdapter = DefaultRouteCalloutAdapter(context)
routeLineView.setCalloutAdapter(viewAnnotationManager, defaultAdapter)
Draw route callouts by passing a list of NavigationRoute
instances 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 callouts 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 map. This includes change in selected primary route, re-drawing callouts after a reroute event, refreshes to update duration, or removal callout of invalid alternatives after the fork is passed.
Be sure to always unregister observers in onStop()
or onDestroy()
.
By default the route callout will be displayed as a bubble with an arrow attached to the route's geometry.
Default adapter behavior and appearance
Display the relative duration on callouts
By default, the API generates callouts for all provided routes and displays the total duration of each route, but in some cases like active navigation while the camera is following the puck it is worth showing callouts only for alternative routes and the related duration difference comparing with the primary one.
val options = DefaultRouteCalloutAdapterOptions.Builder()
.routeCalloutType(RouteCalloutType.NAVIGATION)
.build()
defaultAdapter.updateOptions(options)
Adjust similar duration delta
When routeCalloutType
in the option DefaultRouteCalloutAdapterOptions
sets to RouteCalloutType.NAVIGATION
API may consider an alternative duration the same as the primary one (displaying "Similar ETA" label on callout).
The default value is 3 minutes, it means that any alternative route which duration more or less than 3 minutes comparing to primary one considered as a route with the ETA the same as the primary.
To adjust this threshold update the options as follow:
val options = DefaultRouteCalloutAdapterOptions.Builder()
.routeCalloutType(RouteCalloutType.NAVIGATION)
.similarDurationDelta(1.minutes)
.build()
defaultAdapter.updateOptions(options)
Customize default route callout appearance
There are the set of options that allows to change the appearance of route callout UI component.
To use different colors for callout UI component pass DefaultRouteCalloutAdapterOptions
with following adjustments:
val options = DefaultRouteCalloutAdapterOptions.Builder()
.backgroundColor(R.color.custom_background)
.selectedBackgroundColor(R.color.custom_selected_background)
.textColor(R.color.custom_text_color)
.selectedTextColor(R.color.custom_selected_text_color)
.build()
defaultAdapter.updateOptions(options)
Implement custom adapter
Draw custom route callouts using the Route Line API and an implementation of MapboxRouteCalloutAdapter
.
When you define your adapter, you override two key functions:
onCreateViewHolder
: theMapboxRouteLineView
requests views and their correspondingViewAnnotationOptions
to bind to their data by calling this function in the adapter.onUpdateAnchor
: theMapboxRouteLineView
calls this function when view callout anchor has changed - means that view callout placement relative to its anchor coordinate has been updated.
When your application data has changed and you want MapboxRouteLineView
to redraw callout using this new data you should call the notifyDataSetChanged
function.