Swift 3 - Mapbox - Customize User Location Annotation

前端 未结 1 596
别那么骄傲
别那么骄傲 2021-01-06 09:46

I\'m Looking to change the appearance of the users location annotation. I understand this is now possible using MGLUserLocationAnnotationView, however, I\'m uns

1条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-06 10:08

    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
    

    0 讨论(0)
提交回复
热议问题