I'm Looking to change the appearance of the users location annotation. I understand this is now possible using MGLUserLocationAnnotationView
, however, I'm unsure how to implement this. Can anyone provide a simple example of how this is done?
Thanks
You are right. The MapBox API MGLUserLocationAnnotationView description is very short. The user location view customisation is available since MapBox iOS SDK 3.4.0. See also the feature comments on the MapBox GitHub
It is important to note: The MGLUserLocationAnnotationView is a subclass of the MGLAnnotationView. It means the MGLUserLocationAnnotationView acts just like a normal annotation view.
Here is an example how to customise the user location view. Create a new class (e.g. CustomUserLocationAnnotationView) and override a layoutSubviews() to add a custom code. In this example I use an UIImage UserLocationIcon.png to visualise the user position on the map.
import Foundation
import UIKit
import Mapbox
final class CustomUserLocationAnnotationView: MGLUserLocationAnnotationView {
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
}
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
// Force the annotation view to maintain a constant size when the map is tilted.
scalesWithViewingDistance = false
layer.contentsScale = UIScreen.main.scale
layer.contentsGravity = kCAGravityCenter
// Use your image here
layer.contents = UIImage(named: "UserLocationIcon")?.cgImage
}
}
In your UIViewController or whatever else (e.g. Service class) implement the MGLMapViewDelegate with at least two functions -mapViewDidFinishLoadingMap: and -mapView:viewForAnnotation:. See my comments inline:
extension ViewController: MGLMapViewDelegate {
// Wait until the map is loaded before proceed with other actions on map
func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {
// Show the user location here
mapView.showsUserLocation = true
}
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
// Customise the user location annotation view
if annotation is MGLUserLocation {
var userLocationAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "CustomUserLocationAnnotationViewIdentifier") as? CustomUserLocationAnnotationView
if userLocationAnnotationView == nil {
userLocationAnnotationView = CustomUserLocationAnnotationView(reuseIdentifier: "CustomUserLocationAnnotationViewIdentifier")
}
// Optional: You can save the annotation object for later use in your app
self.userLocationAnnotation = annotation
return userLocationAnnotationView
}
// Customise your annotation view here...
return customAnnotationView
}
}
The MapView -mapView:viewForAnnotation: delegate function is called for every annotation view instance including the user annotation view.
Optionally: To get your CustomUserLocationAnnotationView instance, you can use this function everywhere in your code:
// The userLocationAnnotation was previously saved in your ViewController in the -mapView:viewForAnnotation: delegate function
let view = mapView.view(for: self.userLocationAnnotation) as? CustomUserLocationAnnotationView
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With