In this page

Custom location indicator

这篇文档目前尚未提供译文,将以原文展示。

Customize the location indicator in the Navigation view based on user preferences and add a bottom sheet to allow user-customized actions.

This example shows:

  1. How to add a bottom sheet to allow user-customized actions

  2. How to Custom location indicator in Navigation view based on user preferences

For all code examples, refer to Navigation Code Examples

CustomLocationViewController view source

1import UIKit
2import NbmapNavigation
3import NbmapCoreNavigation
4import NbmapDirections
5import Nbmap
6
7class CustomLocationViewController: UIViewController ,NGLMapViewDelegate{
8   typealias ActionHandler = (UIAlertAction) -> Void
9  
10   var navigationMapView: NavigationMapView! {
11       didSet {
12           oldValue?.removeFromSuperview()
13           if let mapView = navigationMapView {
14               view.insertSubview(mapView, at: 0)
15           }
16       }
17   }
18  
19   var routes : [Route]? {
20       didSet {
21           guard routes != nil else{
22               startButton.isEnabled = false
23               return
24           }
25           startButton.isEnabled = true
26       }
27   }
28  
29   private let startButton = UIButton()
30  
31   override func viewDidLoad() {
32       super.viewDidLoad()
33      
34       self.navigationMapView = NavigationMapView(frame: view.bounds)
35      
36       navigationMapView.userTrackingMode = .follow
37       let singleTap = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(tap:)))
38       navigationMapView?.gestureRecognizers?.filter({ $0 is UILongPressGestureRecognizer }).forEach(singleTap.require(toFail:))
39       navigationMapView?.addGestureRecognizer(singleTap)
40       navigationMapView?.delegate = self
41      
42       let navigationViewportDataSource = NavigationViewportDataSource(navigationMapView)
43       navigationViewportDataSource.options.followingCameraOptions.zoomUpdatesAllowed = false
44       navigationViewportDataSource.followingMobileCamera = NavMapCameraOption()
45       navigationMapView.navigationCamera.viewportDataSource = navigationViewportDataSource
46      
47       setupStartButton()
48   }
49  
50   func setupStartButton() {
51       startButton.setTitle("Start", for: .normal)
52       startButton.layer.cornerRadius = 5
53       startButton.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
54       startButton.backgroundColor = .blue
55      
56       startButton.addTarget(self, action: #selector(performAction), for: .touchUpInside)
57       view.addSubview(startButton)
58       startButton.translatesAutoresizingMaskIntoConstraints = false
59       startButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -50).isActive = true
60       startButton.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor).isActive = true
61       startButton.titleLabel?.font = UIFont.systemFont(ofSize: 25)
62   }
63  
64   @objc func didLongPress(tap: UILongPressGestureRecognizer) {
65       guard let mapView = navigationMapView, tap.state == .began else {
66           return
67       }
68       let coordinates = mapView.convert(tap.location(in: mapView), toCoordinateFrom: mapView)
69       // Note: The destination name can be modified. The value is used in the top banner when arriving at a destination.
70       let destination = Waypoint(coordinate: coordinates, name: "\(coordinates.latitude),\(coordinates.longitude)")
71       addNewDestinationcon(coordinates: coordinates)
72      
73       guard let currentLocation =  mapView.userLocation?.coordinate else { return}
74       let currentWayPoint = Waypoint.init(coordinate: currentLocation, name: "My Location")
75      
76       requestRoutes(origin: currentWayPoint, destination: destination)
77   }
78  
79   @objc func performAction(_ sender: Any) {
80       guard routes != nil else {
81           let alertController = UIAlertController(title: "Create route",
82                                                   message: "Long tap on the map to create a route first.",
83                                                   preferredStyle: .alert)
84           alertController.addAction(UIAlertAction(title: "OK", style: .default))
85           return present(alertController, animated: true)
86       }
87       // Set Up the alert controller to switch between different userLocationStyle.
88       let alertController = UIAlertController(title: "Choose UserLocationStyle",
89                                               message: "Select the user location style",
90                                               preferredStyle: .actionSheet)
91      
92       let courseView: ActionHandler = { _ in self.setupCourseView() }
93       let defaultPuck2D: ActionHandler = { _ in self.setupDefaultPuck2D() }
94       let invisiblePuck: ActionHandler = { _ in self.setupInvisiblePuck() }
95       let puck2D: ActionHandler = { _ in self.setupCustomPuck2D() }
96       let cancel: ActionHandler = { _ in }
97      
98       let actionPayloads: [(String, UIAlertAction.Style, ActionHandler?)] = [
99           ("Invisible Puck", .default, invisiblePuck),
100           ("Default Course View", .default, courseView),
101           ("2D Default Puck", .default, defaultPuck2D),
102           ("2D Custom Puck", .default, puck2D),
103           ("Cancel", .cancel, cancel)
104       ]
105      
106       actionPayloads
107           .map { payload in UIAlertAction(title: payload.0, style: payload.1, handler: payload.2) }
108           .forEach(alertController.addAction(_:))
109      
110       if let popoverController = alertController.popoverPresentationController {
111           popoverController.sourceView = self.startButton
112           popoverController.sourceRect = self.startButton.bounds
113       }
114      
115       present(alertController, animated: true, completion: nil)
116   }
117  
118   func setupCourseView() {
119       presentNavigationViewController(.courseView())
120   }
121  
122   func setupDefaultPuck2D() {
123       presentNavigationViewController(.puck2D)
124   }
125  
126   func setupInvisiblePuck() {
127       presentNavigationViewController(.none)
128   }
129  
130   func setupCustomPuck2D() {
131       let courseView = UserPuckCourseView(frame: CGRect(origin: .zero, size: 75.0))
132       courseView.puckView.image = UIImage(named: "airplane")
133       let userLocationStyle = UserLocationStyle.courseView(courseView)
134       presentNavigationViewController(userLocationStyle)
135   }
136  
137   func presentNavigationViewController(_ userLocationStyle: UserLocationStyle? = nil) {
138       guard let routes = self.routes else {
139           return
140       }
141       let navigationService = NBNavigationService(routes: routes, routeIndex: 0)
142       let navigationOptions = NavigationOptions(navigationService: navigationService)
143       let navigationViewController = NavigationViewController(for: routes,navigationOptions: navigationOptions)
144       navigationViewController.modalPresentationStyle = .fullScreen
145       navigationViewController.navigationMapView?.userLocationStyle = userLocationStyle
146       present(navigationViewController, animated: true, completion: nil)
147   }
148  
149   func addNewDestinationcon(coordinates: CLLocationCoordinate2D){
150       guard let mapView = navigationMapView else {
151           return
152       }
153      
154       if let annotation = mapView.annotations?.last {
155           mapView.removeAnnotation(annotation)
156       }
157      
158       let annotation = NGLPointAnnotation()
159       annotation.coordinate = coordinates
160       mapView.addAnnotation(annotation)
161   }
162  
163   func requestRoutes(origin: Waypoint, destination: Waypoint){
164      
165       let options = RouteOptions.init(origin: origin, destination: destination)
166       // Includes alternative routes in the response
167       options.includesAlternativeRoutes = true
168      
169       // Avoid road options , Set an array road class to avoid.
170       options.roadClassesToAvoid = []
171      
172       // Set the measurement format system
173       options.distanceMeasurementSystem = MeasurementSystem.metric
174      
175       Directions.shared.calculate(options) { [weak self] routes, error in
176           guard let weakSelf = self else {
177               return
178           }
179           guard error == nil else {
180               print(error!)
181               return
182           }
183          
184           guard let routes = routes else { return }
185          
186          
187           // Process or display routes information.For example,display the routes,waypoints and duration symbol on the map
188           weakSelf.navigationMapView?.showRoutes(routes)
189           weakSelf.navigationMapView?.showRouteDurationSymbol(routes)
190          
191           guard let current = routes.first else { return }
192           weakSelf.navigationMapView?.showWaypoints(current)
193           weakSelf.routes = routes
194       }
195   }
196}

This class is a view controller that allows users to add a custom destination marker to a map and then navigate to that destination. The class has the following properties:

  1. navigationMapView: A NavigationMapView object that displays the map.

  2. routes: An array of Route objects that represent the routes between the user's current location and the custom destination marker.

  3. startButton: A UIButton object that is used to start navigation.

The class has the following methods:

  1. viewDidLoad(): This method is called when the view controller is loaded. In this method, the map view is created and configured.

  2. didLongPress(): This method is called when the user long-presses on the map. In this method, a custom destination marker is added to the map at the location of the long press.

  3. performAction(): This method is called when the user taps the "Start Navigation" button. In this method, a navigation controller is created and presented to the user. The navigation controller uses the routes property to display the route between the user's current location and the custom destination marker.

  4. setupStartButton(): This method sets up the "Start Navigation" button.

  5. setupCourseView(): This method sets up the map view to use a course view for the user location.

  6. setupDefaultPuck2D(): This method sets up the map view to use the default 2D puck for the user location.

  7. setupInvisiblePuck(): This method sets up the map view to use an invisible puck for the user location.

  8. setupCustomPuck2D(): This method sets up the map view to use a custom 2D puck for the user location.

  9. presentNavigationViewController(): This method presents a navigation controller for the given routes.

  10. addNewDestinationcon(): This method adds a new destination annotation to the map.

  11. requestRoutes(): This method requests routes between the user's current location and the custom destination marker.

The code also has two extensions:

  1. CustomLocationViewController: NGLMapViewDelegate

  2. CustomLocationViewController: NavigationViewControllerDelegate

These extensions conform the CustomLocationViewController class to the NGLMapViewDelegate and NavigationViewControllerDelegate protocols. These protocols allow the CustomLocationViewController class to respond to events from the map view and the navigation controller.

没找到你要找的内容?