Navigation layer
In NaviKit SDK, MMKNavigationLayer is an additional map layer that includes the user interface (routes, route points, the user placemark, and balloons) and its display logic. MMKNavigationLayer also provides the camera API that lets you change the map position based on navigation scenarios like tracking the user placemark, route overview, and free mode.
Create
To create a new navigation layer, use the MMKNavigationLayerFactory.createNavigationLayer(with:roadEventsLayer:styleProvider:navigation:).
let navigationLayer = MMKNavigationLayerFactory.createNavigationLayer(
with: mapWindow,
roadEventsLayer: roadEventsLayer,
styleProvider: navigationStyleProvider,
navigation: navigation
)
To create roadEventsLayer
, follow these instructions. To create navigation
, follow these instructions.
After you create MMKNavigationLayer, a mark with the current user location will be shown on the map if MMKNavigation has location tracking enabled.
MMKNavigationStyleProvider
To manage UI elements in the navigation layer, use the MMKNavigationStyleProvider interface.
By implementing MMKNavigationStyleProvider, you can set the style of individual UI elements using the required style provider.
- Route polylines: MMKNavigationRouteViewStyleProvider.
- Alternate route and maneuver balloons: MMKNavigationBalloonImageProvider.
- Route points: MMKNavigationRequestPointStyleProvider.
- User placemark model: MMKNavigationUserPlacemarkStyleProvider.
- Route pins: MMKNavigationRoutePinsStyleProvider. Includes traffic light pins and route warnings.
The AutomotiveNavigationStyleProvider
class is a ready-made implementation of the MMKNavigationStyleProvider interface with UI elements in the signature style of API Maps. It's provided as a separate dependency.
To change some UI element styles, implement a new MMKNavigationStyleProvider using AutomotiveNavigationStyleProvider
as a delegate:
class NavigationStyleProviderImpl: NSObject, MMKNavigationStyleProvider {
private let defaultNavigationStyleProvider = AutomotiveNavigationStyleProvider()
// Default style provider implementation
override func balloonImageProvider() = styleProvider.balloonImageProvider()
override func requestPointStyleProvider() = styleProvider.requestPointStyleProvider()
override func userPlacemarkStyleProvider() = styleProvider.userPlacemarkStyleProvider()
override func routePinsStyleProvider() = styleProvider.routePinsStyleProvider()
func routeViewStyleProvider() -> MMKNavigationRouteViewStyleProvider {
routeViewStyleProviderImpl
}
func balloonImageProvider() -> MMKNavigationBalloonImageProvider {
defaultNavigationStyleProvider.balloonImageProvider()
}
func requestPointStyleProvider() -> MMKNavigationRequestPointStyleProvider {
defaultNavigationStyleProvider.requestPointStyleProvider()
}
func userPlacemarkStyleProvider() -> MMKNavigationUserPlacemarkStyleProvider {
defaultNavigationStyleProvider.userPlacemarkStyleProvider()
}
func routePinsStyleProvider() -> MMKNavigationRoutePinsStyleProvider {
defaultNavigationStyleProvider.routePinsStyleProvider()
}
private var routeViewStyleProviderImpl: RouteViewStyleProviderImpl!
private class RouteViewStyleProviderImpl: MMKNavigationRouteViewStyleProvider {
init(defaultNavigationStyleProvider: MMKNavigationStyleProvider) {
routeViewStyleProvider = defaultNavigationStyleProvider.routeViewStyleProvider()
}
private let routeViewStyleProvider: MMKNavigationRouteViewStyleProvider
func provideRouteStyle(
with flags: MMKDrivingFlags,
isSelected: Bool,
isNightMode: Bool,
routeStyle: MMKNavigationRouteStyle
) {
routeViewStyleProvider
.provideRouteStyle(
with: flags,
isSelected: isSelected,
isNightMode: isNightMode,
routeStyle: routeStyle
)
}
// Implementations of other methods through routeViewStyleProvider ...
}
}
That way you can implement a separate MMKNavigationRouteViewStyleProvider style provider for the route line and change how traffic is displayed on routes. Other UI elements are implemented as usual with the AutomotiveNavigationStyleProvider
delegate.
The MMKNavigationStyleProvider styles are refreshed with every call to MMKNavigationLayer.refreshStyle().
There's a detailed example of MMKNavigationStyleProvider implementation in the demo app.
Routes
The navigation layer is responsible for displaying routes in MMKNavigation.
Route display
The navigation layer can display routes on the map. Routes are rendered according to the following scenario:
- When you create MMKNavigationLayer, the MMKNavigation object is passed to it. The layer uses the object to listen to the navigation status and track route changes. For example, when routes are requested, navigation informs you that a route was requested using the MMKNavigationListener.onRoutesRequested(with:) event handler, and the layer switches the camera to route overview mode.
- Navigation then informs you that routes have been built successfully, the MMKNavigationListener.onRoutesBuilt() method is called, and the layer displays routes on the map using the updated data.
That's how the navigation layer tracks route states in MMKNavigation, displays them on the map, and changes them when needed.
Instant guidance
To skip the comparison of alternate routes in overview mode and start guidance along the first found route, start guidance straight after route request results are received in the MMKNavigationListener.onRoutesBuilt() event handler method.
When routes have been requested but guidance hasn't yet started, you may notice that UI routes "blink". Avoid that by hiding the navigation layer UI before starting guidance. Use the MMKNavigationLayer.isVisible method or hide the route lines using style override through NavigationStyleProvider.
Route sources
MMKNavigationLayer.routesSource determines the type of routes the navigation layer is currently displaying:
- navigation: The result of a route request via MMKNavigation when routes are displayed in overview mode.
- guidance: The current route during guidance when routes are displayed in guidance mode.
Current route
MMKNavigationLayer stores information about the currently selected route. By calling MMKNavigationLayer.selectRoute(withRoute:), you can change the currently selected route in overview mode.
Here's an example of how to set the current route:
class RouteViewListener: NSObject, MMKRouteViewListener {
func onRouteViewTap(withRoute: MMKRouteView) {
switch navigationLayer.routesSource {
case .navigation:
navigationLayer.selectRoute(withRoute: routeView)
case .guidance:
navigationLayer.navigation.switchToRoute(with: routeView.route)
}
}
func onRouteViewsChanged() {
guard navigationLayer.selectedRoute() == nil,
let route = navigationLayer.routes.first else {
return
}
navigationLayer.selectRoute(withRoute: route)
}
}
let routeViewListener = RouteViewListener()
navigationLayer.addRouteViewListener(with: routeViewListener)
To track route states in the navigation layer, use the MMKRouteViewListener interface.
- MMKRouteViewListener.onRouteViewsChanged() informs you about route changes in MMKNavigationLayer. If the selected route isn't there, the fastest (first) route is selected instead.
- MMKRouteViewListener.onRouteViewTap(withRoute:) processes the event of tapping the route line on the map.
Note
The navigation layer doesn't contain the current route by default after routes are requested through MMKNavigation. You have to set it manually, for example, using MMKRouteViewListener.onRouteViewsChanged().
Route points
The navigation layer is responsible for displaying the from, to, and via points in guidance and overview modes.
To track point changes and taps, use the MMKRequestPointListener interface.
User placemark
A user placemark is a model that displays the current user location and direction on the map. It consists of an OBJ
file and PNG
texture.
Balloons
Balloons are UI elements with text on the map. There are different types of balloons:
- Maneuver balloons show the next maneuver on the map in guidance mode.
- Alternative balloons show route information in overview mode and compare the current and selected routes.
Use the MMKBalloonViewListener interface to follow balloon events.
Camera
To manage the camera, use the MMKCamera object by calling MMKNavigationLayer.camera.
To switch between camera modes, use the MMKCamera.setCameraModeWith(_:animation:) method. Supported modes:
- Following: The user placemark tracked by the camera during guidance.
- Overview: An overview of requested routes.
- Free: The default mode.
By default, MMKCamera has full control over the map and automatically changes the camera status. When using special camera modes, you may want to restrict camera permissions.
With the MMKCamera and MMKNavigationLayer methods, you can change the following camera parameters:
- Automatic zoom-in.
- Automatic turn.
- Automatic switch between camera modes.
- Zoom-in correction parameter in guidance mode.
- 2D mode on/off.
If you create a complex interface over the map, UI elements may cover some map areas. You can prevent that by configuring the visible area parameters.
Supported settings for the visible map area:
- MMKCamera.setOverviewRectWith(_:animation:): Determines the map area where routes are displayed in overview mode.
- MMKCamera.setExtraOverviewPointsWith(_:): Sets a list of points that must be visible on the map in overview mode.