Shekar
Shekar

Reputation: 250

how to animate drop of MKAnnotationView with custom image

when I try to access the animate drop property of an MKAnnotationView, it doesn't exist. I know this property exists for a MKPinAnnotationView, but I'm using a custom image and therefore have to use a MKAnnotationView. Any way to animate the drop of a MKAnnotationView? Code:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation { return nil }

    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pinIdentifier)
    if annotationView == nil {
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: pinIdentifier)
        annotationView?.canShowCallout = true

        let pinImage = UIImage(named:"mappin")!
        annotationView?.image = pinImage
        //annotationView?.animatesDrop = true

    } else {
        annotationView?.annotation = annotation
    }
    return annotationView
}

Upvotes: 1

Views: 863

Answers (1)

Brandon A
Brandon A

Reputation: 8279

1) Create a xib file and an associated .swift file to hold your AnimatedAnnotation code.

pics

2) in AnimatedAnnotation.xib you can put your UI creativity to task and create your annotation.

enter image description here

3) In your AnimatedAnnotation.swift file, create your own AnimatedAnnotation class.

class AnimatedAnnotation: MKAnnotationView {


}

4) Next, write a configuration method that will configure an instance of this "invisible" container view with an animationDuration, and annotationImage (this will be your custom image).

class AnimatedAnnotation: UIView {

    var animationDuration: Double!
    var annotationImage: UIImage!

    func configureWith(animationDuration: Double, annotationImage: UIImage) {
        self.backgroundColor = .clear
        self.annotationImage = annotationImage
        self.animationDuration = animationDuration
    }
}

5) Then declare a property animatedView of type UIImageView and instantiate it within your configuration block.

class AnimatedAnnotation: UIView {

    var animatedView: UIImageView!
    var animationDuration: Double!
    var annotationImage: UIImage!

    func configureWith(animationDuration: Double, annotationImage: UIImage) {
        self.backgroundColor = .clear
        self.annotationImage = annotationImage
        self.animationDuration = animationDuration
        instantiateAnimatedView()
    }

    func instantiateAnimatedView() {
        let startingPosition = CGRect(x: 0, y: 0, width: 20, height: 20) // This is whatever starting position you want
        let imageView = UIImageView(frame: startingPosition)
        imageView.image = UIImage(name: "YourAnnotationImage")
        imageView.alpha = 0
        addSubview(imageView!)
    }
}

6) Write the method to make the animated view appear and animate on top of it's "invisible" superview.

class AnimatedAnnotation: UIView {

    var animatedView: UIImageView!
    var animationDuration: Double!
    var annotationImage: UIImage!

    func configureWith(animationDuration: Double, annotationImage: UIImage) {
        self.backgroundColor = .clear
        self.annotationImage = annotationImage
        self.animationDuration = animationDuration
        instantiateAnimatedView()
        dropAnnotation() // Call whenever you want the drop to happen
    }

    func instantiateAnimatedView() {
        let startingPosition = CGRect(x: 0, y: 0, width: 20, height: 20) // This is whatever starting position you want
        let imageView = UIImageView(frame: startingPosition)
        imageView.image = annotationImage
        imageView.alpha = 0
        addSubview(imageView!)
    }

    func dropAnnotation() {
        let dropHeight:CGFloat = self.bounds.size.height - animatedView.frame.size.height
        let endPosition = CGPoint(x: animatedView.center.x, y: animatedView.center.y + dropHeight)
        UIView.animate(withDuration: animationDuration, animations: {
             self.animatedView.alpha = 1
             self.animatedView.center = endPosition
        })
    }
}

7) USAGE in your viewFor annotation: MKAnnotation) -> MKAnnotationView? method, instantiate an AnimatedAnnotation and return that in the method.

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let bundle = Bundle.main // or your framework bundle
    let xib = UINib(nibName: "AnimatedAnnotation", bundle: bundle)
    let view = xib.instantiate(withOwner: self, options: nil)[0] as! AnimatedAnnotation
    view.configureWith(animationDuration: 0.25, annotationImage: UIImage(named: "Your-Annotation-Image")
    return view
}

I haven't actually tried this in Xcode, and I just wrote this in the SO editor, but this should work. Let me know your progress.

Upvotes: 2

Related Questions