How do I animate MKAnnotationView drop?

随声附和 提交于 2019-11-26 10:31:41

问题


I have a custom MKAnnotationView where I set my image myself in viewForAnnotation. How do I animate it\'s drop like I can with MKPinAnnotationView?

My code is

- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
    static NSString *AnnotationViewID = @\"annotationViewID\";

    MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];

    if (annotationView == nil)
    {
        annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID] autorelease];
    }

    annotationView.image = [UIImage imageNamed:@\"blah.png\"];
    annotationView.annotation = annotation;

    return annotationView;
}

回答1:


Implement the didAddAnnotationViews delegate method and do the animation yourself:

- (void)mapView:(MKMapView *)mapView 
          didAddAnnotationViews:(NSArray *)annotationViews
{
    for (MKAnnotationView *annView in annotationViews)
    {
        CGRect endFrame = annView.frame;
        annView.frame = CGRectOffset(endFrame, 0, -500);
        [UIView animateWithDuration:0.5 
                animations:^{ annView.frame = endFrame; }];
    }
}



回答2:


One problem with the code above by Anna Karenina is that it doesn't deal with when you add annotations below where the user is looking at the moment. Those annotations will float in mid-air before dropping because they are moved into the user's visible map rect.

Another is that it also drops the user location blue dot. With this code below, you handle both user location and large amounts of map annotations off-screen. I've also added a nice bounce ;)

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
    MKAnnotationView *aV; 

    for (aV in views) {

        // Don't pin drop if annotation is user location
        if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
            continue;
        }

        // Check if current annotation is inside visible map rect, else go to next one
        MKMapPoint point =  MKMapPointForCoordinate(aV.annotation.coordinate);
        if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
            continue;
        }

        CGRect endFrame = aV.frame;

        // Move annotation out of view
        aV.frame = CGRectMake(aV.frame.origin.x, aV.frame.origin.y - self.view.frame.size.height, aV.frame.size.width, aV.frame.size.height);

        // Animate drop
        [UIView animateWithDuration:0.5 delay:0.04*[views indexOfObject:aV] options: UIViewAnimationOptionCurveLinear animations:^{

            aV.frame = endFrame;

        // Animate squash
        }completion:^(BOOL finished){
            if (finished) {
                [UIView animateWithDuration:0.05 animations:^{
                    aV.transform = CGAffineTransformMakeScale(1.0, 0.8);

                }completion:^(BOOL finished){
                    if (finished) {
                        [UIView animateWithDuration:0.1 animations:^{
                            aV.transform = CGAffineTransformIdentity;
                        }];
                    }
                }];
            }
        }];
    }
}



回答3:


@MrAlek's Answer for swift3

optional func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
    print(#function)

    var i = -1;
    for view in views {
        i += 1;
        if view.annotation is MKUserLocation {
            continue;
        }

        // Check if current annotation is inside visible map rect, else go to next one
        let point:MKMapPoint  =  MKMapPointForCoordinate(view.annotation!.coordinate);
        if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
            continue;
        }

        let endFrame:CGRect = view.frame;

        // Move annotation out of view
        view.frame = CGRect(origin: CGPoint(x: view.frame.origin.x,y :view.frame.origin.y-self.view.frame.size.height), size: CGSize(width: view.frame.size.width, height: view.frame.size.height))

        // Animate drop
        let delay = 0.03 * Double(i)
        UIView.animate(withDuration: 0.5, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations:{() in
            view.frame = endFrame
            // Animate squash
            }, completion:{(Bool) in
                UIView.animate(withDuration: 0.05, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in
                    view.transform = CGAffineTransform(scaleX: 1.0, y: 0.6)

                    }, completion: {(Bool) in
                        UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations:{() in
                            view.transform = CGAffineTransform.identity
                            }, completion: nil)
                })

        })
    }
}



回答4:


@mrAlek answer in Swift:

func mapView(mapView: MKMapView!, didAddAnnotationViews views: [AnyObject]!) {
    println("didAddAnnotationViews()")

    var i = -1;
    for view in views {
        i++;
        let mkView = view as! MKAnnotationView
        if view.annotation is MKUserLocation {
            continue;
        }

        // Check if current annotation is inside visible map rect, else go to next one
        let point:MKMapPoint  =  MKMapPointForCoordinate(mkView.annotation.coordinate);
        if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
            continue;
        }

        let endFrame:CGRect = mkView.frame;

        // Move annotation out of view
        mkView.frame = CGRectMake(mkView.frame.origin.x, mkView.frame.origin.y - self.view.frame.size.height, mkView.frame.size.width, mkView.frame.size.height);

        // Animate drop
        let delay = 0.03 * Double(i)
        UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in
            mkView.frame = endFrame
            // Animate squash
            }, completion:{(Bool) in
                        UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
                            mkView.transform = CGAffineTransformMakeScale(1.0, 0.6)

                        }, completion: {(Bool) in
                                UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
                                    mkView.transform = CGAffineTransformIdentity
                                    }, completion: nil)
                        })

                    })
    }
}



回答5:


@MrAlek's answer in Swift 2:

func mapView(mapView: MKMapView, didAddAnnotationViews views: [MKAnnotationView]) {
    print(__FUNCTION__)

    var i = -1;
    for view in views {
        i++;
        if view.annotation is MKUserLocation {
            continue;
        }

        // Check if current annotation is inside visible map rect, else go to next one
        let point:MKMapPoint  =  MKMapPointForCoordinate(view.annotation!.coordinate);
        if (!MKMapRectContainsPoint(self.mapView.visibleMapRect, point)) {
            continue;
        }

        let endFrame:CGRect = view.frame;

        // Move annotation out of view
        view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y - self.view.frame.size.height, view.frame.size.width, view.frame.size.height);

        // Animate drop
        let delay = 0.03 * Double(i)
        UIView.animateWithDuration(0.5, delay: delay, options: UIViewAnimationOptions.CurveEaseIn, animations:{() in
            view.frame = endFrame
            // Animate squash
            }, completion:{(Bool) in
                UIView.animateWithDuration(0.05, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
                    view.transform = CGAffineTransformMakeScale(1.0, 0.6)

                    }, completion: {(Bool) in
                        UIView.animateWithDuration(0.3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations:{() in
                            view.transform = CGAffineTransformIdentity
                            }, completion: nil)
                })

        })
    }
}



回答6:


Updated for Swift 4.2

   func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
    var i = -1;
    for view in views {
        i += 1;
        if view.annotation is MKUserLocation {
            continue;
        }
        let point:MKMapPoint  =  MKMapPoint(view.annotation!.coordinate);
        if (!self.mapView.visibleMapRect.contains(point)) {
            continue;
        }
        let endFrame:CGRect = view.frame;
        view.frame = CGRect(origin: CGPoint(x: view.frame.origin.x,y :view.frame.origin.y-self.view.frame.size.height), size: CGSize(width: view.frame.size.width, height: view.frame.size.height))
        let delay = 0.03 * Double(i)
        UIView.animate(withDuration: 0.5, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations:{() in
            view.frame = endFrame
        }, completion:{(Bool) in
            UIView.animate(withDuration: 0.05, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations:{() in
                view.transform = CGAffineTransform(scaleX: 1.0, y: 0.6)
            }, completion: {(Bool) in
                UIView.animate(withDuration: 0.3, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations:{() in
                    view.transform = CGAffineTransform.identity
                }, completion: nil)
            })
        })
    }
}


来源:https://stackoverflow.com/questions/6808876/how-do-i-animate-mkannotationview-drop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!