Cocoa touch 如何设置MKAnnotationView drop的动画?
我有一个自定义的MKAnnotationView,在这里我自己在viewForAnnotation中设置图像。如何使用MKPinAnnotationView设置其下落的动画 我的代码是Cocoa touch 如何设置MKAnnotationView drop的动画?,cocoa-touch,ios-4.2,mkannotationview,mkpinannotationview,mapkit,Cocoa Touch,Ios 4.2,Mkannotationview,Mkpinannotationview,Mapkit,我有一个自定义的MKAnnotationView,在这里我自己在viewForAnnotation中设置图像。如何使用MKPinAnnotationView设置其下落的动画 我的代码是 - (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation { static NSString *AnnotationViewID = @"annotationVi
- (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;
}
-(MKAnnotationView*)地图视图:(MKMapView*)地图视图注释:(id)注释
{
静态NSString*AnnotationViewID=@“AnnotationViewID”;
MKAnnotationView*annotationView=(MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
如果(注释视图==nil)
{
annotationView=[[MKAnnotationView alloc]initWithAnnotation:annotation重用标识符:AnnotationViewID]自动释放];
}
annotationView.image=[UIImage ImageName:@“blah.png”];
annotationView.annotation=注释;
返回注释视图;
}
执行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; }];
}
}
安娜·卡列尼娜(Anna Karenina)的上述代码的一个问题是,当您在下面用户正在查看的地方添加注释时,它无法处理。这些注释在放下之前会漂浮在半空中,因为它们会被移动到用户的可见地图矩形中 另一个原因是,它还删除了用户位置的蓝点。使用下面的代码,您可以在屏幕外处理用户位置和大量地图注释。我还添加了一个漂亮的反弹;)
@mrAlek用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)
})
})
}
}
@MrAlek在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)
})
})
}
}
@MrAlek对迅捷3的回答
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)
})
})
}
}
更新为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)
})
})
}
}
除了在
MKMapViewDelegate
中实现mapView(uquo:diddad:)
,您还可以让注释视图本身执行动画
class CustomAnnotationView: MKAnnotationView {
override var annotation: MKAnnotation? { didSet { update(for: annotation) } }
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
update(for: annotation)
}
override func prepareForReuse() {
super.prepareForReuse()
removeFromSuperview()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
transform = CGAffineTransform(translationX: 0, y: -100)
alpha = 0
UIViewPropertyAnimator(duration: 0.5, dampingRatio: 0.4) {
self.transform = .identity
self.alpha = 1
}.startAnimation()
}
private func update(for annotation: MKAnnotation?) {
// do whatever update to the annotation view you want, if any
}
}
这有助于避免视图控制器与注释视图动画的混乱。例如,在iOS 11及更高版本中,您可以执行以下操作:
mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
然后,您可以将注释添加到地图视图中,并在视图控制器中获得注释视图的动画,而无需任何其他代码
这个特定的动画是一个在结尾有一点反弹的下降,但是显然你可以做任何你想要的动画
上面的内容是用Swift编写的,但这个概念在Objective-C中也同样有效。谢谢,这很有效!如何使其反弹而不是从顶部插入?您可以将所有UIView动画技术用于注释视图(它是UIView的子类)。上面的示例仅更改y坐标,但您可以执行其他变换。例如,搜索类似“uiview反弹动画”的内容。这里有一个:。您需要添加QuartzCore框架,导入它,并将“视图”更改为“annView”。@Annakarena但是我们如何才能将CustomView添加为我们的pinView和customCallOut任何引用。谢谢@MrAlek,它有很好的动画。这太棒了!非常感谢;)这不是一个拖放动画,只是一个很好的动画
mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)