26

Tengo una MKAnnotationView personalizada donde configuro mi imagen en viewForAnnotation. ¿Cómo puedo animar su caída como puedo con MKPinAnnotationView?¿Cómo puedo animar MKAnnotationView drop?

Mi código es

- (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; 
} 

Respuesta

46

implementar el método delegado didAddAnnotationViews y hacer la animación a sí mismo:

- (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; }]; 
    } 
} 
+0

¡Gracias, eso funcionó! ¿Cómo lo haría rebotar en lugar de caer desde arriba? – DeShawnT

+1

Puede usar todas las técnicas de animación de UIView con la vista de anotación (es una subclase de UIView). El ejemplo anterior simplemente cambia la coordenada y pero puede hacer otras transformaciones. Busque SO para algo como "uiview bounce animation" para ver ejemplos. Aquí hay uno: http://stackoverflow.com/questions/2160150/mimic-uialertview-bounce/4200005#4200005. Deberá agregar QuartzCore framework, importarlo y cambiar "view" a "annView". – Anna

+0

@AnnaKarenina, pero ¿cómo podemos agregar CustomView como nuestro pinView y customCallOut referencias. – AJPatel

55

Un problema con el código anterior por Anna Karenina es que no se ocupa de cuando agrega anotaciones a continuación donde el usuario está mirando el momento. Esas anotaciones flotarán en el aire antes de caer porque se moverán al mapa visible del usuario.

Otra es que también deja caer el punto azul de la ubicación del usuario. Con este código a continuación, maneja la ubicación del usuario y grandes cantidades de anotaciones de mapa fuera de la pantalla. También he añadido un buen rebote;)

- (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; 
         }]; 
        } 
       }]; 
      } 
     }]; 
    } 
} 
+0

Gracias @MrAlek, tiene buena animación. – Ravin

+0

¡Reparado! Buen lugar. – MrAlek

5

respuesta @mrAlek en 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

@ respuesta de MrAlek en 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) 
       }) 

     }) 
    } 
} 
+0

¡Esto es brillante! Muchas gracias ;) –

7

@ respuesta de MrAlek para 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) 
       }) 

     }) 
    } 
}