Route arrow
The Navigation SDK allows you to display an arrow on a map that illustrates the next maneuver as a user navigates along a route. This is a common UI component used in turn-by-turn navigation applications.
Use the route maneuver arrow UI component
The route maneuver arrow UI component consists of two main classes:
- The
MapboxRouteArrowApi
consumesRouteProgress
objects and calculates an arrow for the next maneuver. - The
MapboxRouteArrowView
class handles consuming the calculated arrow data and rendering an arrow on the map.
By default the route maneuver arrow will be displayed as a white arrow on top of the route line (if it exists) or on top of all features in the map. It will be visible for the maneuver that is next based on the device location.
Instantiate the route maneuver arrow API
Instantiate the MapboxRouteArrowApi
and MapboxRouteArrowView
classes in your Activity
or Fragment
.
val routeArrow = MapboxRouteArrowApi()
val routeArrowOptions = RouteArrowOptions.Builder(context).build()
val routeArrowView = MapboxRouteArrowView(routeArrowOptions)
To show the next maneuver arrow, register a RouteProgressObserver
with MapboxNavigation
. When a RouteProgress
object is received, call the MapboxRouteArrowApi
and pass the result of the arrow calculation to the render method of MapboxRouteArrowView
.
private val routeProgressObserver = object : RouteProgressObserver {
override fun onRouteProgressChanged(routeProgress: RouteProgress) {
val updatedManeuverArrow = routeArrow.addUpcomingManeuverArrow(routeProgress)
routeArrowView.renderManeuverUpdate(mapStyle, updatedManeuverArrow)
}
}
Be sure to always unregister observers in onStop()
or onDestroy()
.
Customize the route maneuver arrow
There are several ways to customize the route maneuver arrow UI component using RouteArrowOptions
.
Position the route arrow 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 maneuver arrow UI component consists of layers that are added to the map.
By default, the maneuver arrow will be placed on top of all the other layers in the map. This is not always the most optimal position for a route arrow because it may appear on top of road labels and other labels on the map. You can specify the route arrow layers' position within all map layers using the aboveLayerId
parameter of the RouteArrowOptions
. When the maneuver arrow layers are created they will be placed above the layer specified by the aboveLayerId
option.
We recommend RouteLayerConstants.TOP_LEVEL_ROUTE_LINE_LAYER_ID as a good starting point which will place the route arrows right above the route line.
val routeArrowOptions = RouteArrowOptions.Builder(this)
.withAboveLayerId(RouteLayerConstants.TOP_LEVEL_ROUTE_LINE_LAYER_ID)
.build()
Add custom arrows
The Navigation SDK supports displaying multiple arrows on the map. An arrow is defined by a collection of at least two Point
objects. The arrowhead is placed at the last point in the collection and the direction of the arrowhead is determined by calculating the bearing of the last two points in the collection.
Arrows can be added to and removed from the map before and during navigation. While the next maneuver arrow is managed by the MapboxRouteArrowApi
class, it is up to you to manage any other arrows you add to the map.
To add a custom arrow, create an arrow using ManeuverArrow
and add it to the view.
val myArrow = ManeuverArrow(
listOf(
Point.fromLngLat(-122.432034, 37.775755),
Point.fromLngLat(-122.431229, 37.775865),
Point.fromLngLat(-122.431293, 37.776255)
)
)
val result = mapboxArrowApi.addArrow(myArrow)
routeArrowView.render(style, result)
To remove an arrow you've added before:
val result = mapboxArrowApi.removeArrow(myArrow)
routeArrowView.render(style, result)