26

我有一個自定義的MKAnnotationView,我在viewForAnnotation中自己設置自己的圖像。我如何使用MKPinAnnotationView對它進行動畫處理?如何爲MKAnnotationView放置動畫?

我的代碼是

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

回答

46

落實didAddAnnotationViews委託方法,做動畫的自己:

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

謝謝,工作!我將如何使它反彈而不是從頂端下降? – DeShawnT

+1

您可以將所有UIView動畫技術與註釋視圖(它是UIView的子類)一起使用。上面的例子只是改變y座標,但你可以做其他的轉換。以搜索爲例如「uiview bounce animation」的例子。這裏有一個:http://stackoverflow.com/questions/2160150/mimic-uialertview-bounce/4200005#4200005。您需要添加QuartzCore框架,將其導入並將「視圖」更改爲「annView」。 – Anna

+0

@AnnaKarenina,但我們如何添加CustomView作爲我們的pinView和customCallOut的任何引用。 – AJPatel

55

一個由安娜·卡列尼娜上面的代碼問題是,它不處理時您可以在用戶正在查看的位置下方添加註釋。這些註釋在下落前會在半空中浮動,因爲它們被移動到用戶的可見地圖矩形中。

另一個是它也會丟棄用戶位置的藍點。通過以下代碼,您可以在屏幕外同時處理用戶位置和大量地圖註釋。我還添加了一個漂亮的反彈;)

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

感謝@MrAlek,它有很好的動畫效果。 – Ravin

+0

固定!好點。 – MrAlek

5

@mrAlek答案斯威夫特:

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的答案斯威夫特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

這太棒了!非常感謝 ;) –

7

@ MrAlek的答案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) 
       }) 

     }) 
    } 
}