User interface
The Navigation SDK provides several pre-built UI components that you can use to build a complete user interface for a turn-by-turn navigation application. Drop components into your application using their default configuration or customize the components' behavior and appearance to create a completely unique experience for your users.
Use the drop-in UI
The Navigation SDK for iOS offers a complete drop-in UI, NavigationViewController
.
NavigationViewController
embeds a NavigationView
that contains the following UI components with appropriate functionality included by default:
InstructionsBannerView
: Maneuver instructionsInformationStackView
: Additional maneuver instructions informationBottomBannerViewController
: Trip progressResumeButton
: Resume buttonWayNameLabel
: Label for current wayFloatingStackView
: Camera, volume, and feedback buttonsNavigationMapView
: Map a displaying route line and user locationSpeedLimitView
: Speed limit
+--------------------+
| 1 |
+--------------------+
| 2 |
+---+------------+---+
| 8 | | |
+---+ | 6 |
| | |
| 7 +---+
| |
| |
| |
+------------+ |
| 4 || 5 | |
+------------+-------+
| 3 |
+--------------------+
Present a navigation view controller
For an example of how to initialize NavigationViewController
, see the Request a route section of the Installation guide.
Maneuver instructions
NavigationViewController
uses logic from Mapbox Core Navigation to trigger a comprehensive system of visual and spoken instructions by default. There are default styling rules for visual instructions and default settings for voice instructions. Instructions can be customized to synchronize your application's behavior with instructions coming from the Mapbox Navigation SDK and customizing the style of visual instructions to fit with your application.
Default visual instructions
The default TopBannerViewController
UI component shows maneuver instructions. It is refreshed by route progress events and displays the following pieces of information:
- Primary visual instruction: Shows the name of the road, freeway, or exit of the next maneuver.
- Secondary visual instruction (optional): Shows more information about the road, freeway, or exit if available.
- Tertiary visual instruction (optional): Shows either the name of the road, freeway, or exit of the maneuver after the next maneuver if it will occur shortly after completing the next maneuver, or guides the user to drive in the appropriate lane if there are multiple lanes and an upcoming maneuver requires them to be in a specific lane.
- Quaternary visual instruction (optional): In some regions, a graphical representation of the layout of a freeway exit.
- Upcoming maneuver list: Shows a list of upcoming maneuvers excluding the current maneuver.
A user can also tap or swipe down on TopBannerViewController
to view a full list of maneuvers for the trip.
Listen for changes to visual instructions
By default, visual instructions will be displayed when NavigationServiceDelegate.navigationService(_:didPassVisualInstructionPoint:routeProgress:)
is called and Notification.Name.routeControllerDidPassVisualInstructionPoint
is posted when the user passes the appropriate point at which to display a visual instruction. A visual instruction point occurs near the beginning of a step. There may be additional visual instruction points along the step as additional information, like turn lanes, become relevant.
You can use VisualInstructionDelegate.label(_:willPresent:as:)
to adjust the predefined contents of visual instruction provided by the Directions API, but you cannot currently trigger an arbitrary message outside the visual instructions that are triggered by default.
func label(_ label: InstructionLabel, willPresent instruction: VisualInstruction, as presented: NSAttributedString) -> NSAttributedString? {
let range = NSRange(location: 0, length: presented.length)
let mutable = NSMutableAttributedString(attributedString: presented)
mutable.mutableString.applyTransform(.latinToKatakana, reverse: false, range: range, updatedRange: nil)
return mutable
}
Listen for changes to spoken instructions
By default, spoken instructions will be played when NavigationServiceDelegate.navigationService(_:didPassSpokenInstructionPoint:routeProgress:)
is called and Notification.Name.routeControllerDidPassSpokenInstructionPoint
is posted when the user passes the appropriate point at which to announce a spoken instruction. A spoken instruction point occurs near the end of a step. There may be additional spoken instruction points, as time allows, at a comfortable distance before the end of the step and near the beginning of the step. A single spoken instruction point may correspond to an instruction about two successive maneuvers nearby.
You can also trigger arbitrary voice instructions by calling SpeechSynthesizer.speak(_:during:locale:)
.
Trip progress
Many navigation applications display data related to trip progress including the estimated time to arrival and the distance remaining. NavigationViewController
includes a trip progress UI. The SDK uses the RouteProgress
class to hold information about your user's progress along a route. The information is then used to display indicators of trip progress on the device's screen. Read more about the information included in the route progress object in the Route progress guide.
The default BottomBannerViewController
UI component illustrates the user's progress along a route. It is refreshed by route progress events and displays:
- Estimated time to arrival
- Distance remaining
- Estimated time remaining
Map
While applications using the Navigation SDK don't have to include a map, many use cases will require maps to provide an appropriate navigation experience to your users. By default, NavigationViewController
uses the Mapbox Maps SDK for iOS to display routes on a map and show the user's location on the map throughout their trip to provide both navigation-related context and nearby places that may be of interest to the driver.
Read more about using maps in the Maps for navigation guide.
Speed limit
The speed limit UI included in NavigationViewController
, SpeedLimitView
, displays the speed limit of the road the user is currently traveling on.
Map buttons
NavigationViewController
includes several buttons for the user to control the behavior of the application including:
Function | Button | Description |
---|---|---|
Route overview | Zoom out to an overview of the full route at any time during navigation. | |
Resume navigation | Zoom back in to the current location after viewing the route overview or after panning around the map manually. | |
Volume control | Mute or unmute voice instructions. | |
Feedback | Provide route or map feedback. |
Customize NavigationViewController
App styling
When using NavigationViewController
, it's possible to apply custom fonts and colors to various parts of the UI. The easiest way to find elements and their class name to style is to use the Debug View Hierarchy feature in Xcode.
- While running your app, select the Debug View Hierarchy button.
- Select the view you wish to style.
- On the right side of your screen, note the class name.
- Apply your styling:
DistanceLabel.appearance(for: UITraitCollection(userInterfaceIdiom: .phone), whenContainedInInstancesOf: [InstructionsBannerView.self]).unitTextColor = .red
DistanceLabel.appearance(for: UITraitCollection(userInterfaceIdiom: .pad), whenContainedInInstancesOf: [InstructionsBannerView.self]).unitTextColor = .green
Remember to apply such styling in Style.apply()
method.
It is also helpful to view the default styling applied by the DayStyle
.
Spoken instruction override
Override a spoken instruction with a custom instruction.
func voiceController(_ voiceController: RouteVoiceController, willSpeak instruction: SpokenInstruction, routeProgress: RouteProgress) -> SpokenInstruction? {
return SpokenInstruction(distanceAlongStep: instruction.distanceAlongStep, text: "New Instruction!", ssmlText: "<speak>New Instruction!</speak>")
}
Language
For customizing the language used in visual and spoken instructions, see Localization and internationalization.
Build a custom UI
If you want to build a completely customizable turn-by-turn experience, you can use some of the Navigation SDK's UI components used in NavigationViewController
individually or build your own components from scratch.
Top banner
The Navigation SDK offers InstructionsCardViewController
as a pre-built alternative to the default TopBannerViewController
to display maneuver instructions as a “card” resembling a user notification. In InstructionsCardViewController
, the next maneuver is partially visible on one side of the view and swiping to one side reveals the full maneuver.
Replace TopBannerViewController
with InstructionsCardViewController
when using NavigationViewController
:
let instructionsCardCollection = InstructionsCardViewController()
let navigationOptions = NavigationOptions(bottomBanner: instructionsCardCollection)
let navigationViewController = NavigationViewController(for: response, routeIndex: 0, routeOptions: routeOptions, navigationOptions: navigationOptions)
instructionsCardCollection.navigationViewController = navigationViewController
You can also replace the default TopBannerViewController
with a custom view that shows anything you'd like to occupy the top banner position. Create your custom view:
class CustomTopBannerViewController: ContainerViewController, CustomBottomBannerViewDelegate { // build custom view}
Then use the code above, but substitute your CustomTopBannerViewController
for InstructionsCardViewController
.
Bottom banner
When using NavigationViewController
you can replace the default BottomBannerViewController
that shows trip progress with a custom view that shows trip progress or anything else you'd like to occupy the bottom banner position.
Start by creating your custom view:
class CustomBottomBarViewController: ContainerViewController, CustomBottomBannerViewDelegate {
// build custom view
}
Then pass your custom implementations of the bottom banner to NavigationOptions
. If you do not specify a bottomBanner
explicitly, the default BottomBannerViewController
will be used by default.
let bottomBanner = CustomBottomBarViewController()
let navigationOptions = NavigationOptions(bottomBanner: bottomBanner)
let navigationViewController = NavigationViewController(for: response, routeIndex: 0, routeOptions: routeOptions, navigationOptions: navigationOptions)
bottomBanner.navigationViewController = navigationViewController
Substitute the default top and bottom banners with custom view controllers.
Spoken instructions
An application can call RouteVoiceController.speak(_:)
at any time to interrupt any in-progress spoken instruction with a custom spoken instruction.
For more information on supported SSML tags see Amazon's SSML Tags Supported by Amazon Polly guide.