gpt4 book ai didi

ios - MKAnnotationView 拖动状态结束动画

转载 作者:行者123 更新时间:2023-12-01 17:30:32 27 4
gpt4 key购买 nike

我在这里使用 Daniel 提供的自定义 MKAnnotationView 动画:Subclassing MKAnnotationView and overriding setDragState但我遇到了一个问题。

在 pin 放置动画之后,当我移动 map 时,mkannotationview 会在调用最终 pin 放置动画 block 之前跳回其先前的位置。

在我看来,在动画运行之前调用了 dragState=MKAnnotationViewDragStateEnding 吗?如何解决此问题并将 mkannotationview 的最终点设置为动画结束时的点?

#import "MapPin.h"

NSString *const DPAnnotationViewDidFinishDrag = @"DPAnnotationViewDidFinishDrag";
NSString *const DPAnnotationViewKey = @"DPAnnotationView";

// Estimate a finger size
// This is the amount of pixels I consider
// that the finger will block when the user
// is dragging the pin.
// We will use this to lift the pin even higher during dragging

#define kFingerSize 20.0

@interface MapPin()
@property (nonatomic) CGPoint fingerPoint;
@end

@implementation MapPin
@synthesize dragState, fingerPoint, mapView;

- (void)setDragState:(MKAnnotationViewDragState)newDragState animated:(BOOL)animated
{
if(mapView){
id<MKMapViewDelegate> mapDelegate = (id<MKMapViewDelegate>)mapView.delegate;
[mapDelegate mapView:mapView annotationView:self didChangeDragState:newDragState fromOldState:dragState];
}

// Calculate how much to life the pin, so that it's over the finger, no under.
CGFloat liftValue = -(fingerPoint.y - self.frame.size.height - kFingerSize);

if (newDragState == MKAnnotationViewDragStateStarting)
{
CGPoint endPoint = CGPointMake(self.center.x,self.center.y-liftValue);
[MapPin animateWithDuration:0.2
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateDragging;
}];

}
else if (newDragState == MKAnnotationViewDragStateEnding)
{
// lift the pin again, and drop it to current placement with faster animation.

__block CGPoint endPoint = CGPointMake(self.center.x,self.center.y-liftValue);
[MapPin animateWithDuration:0.2
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
endPoint = CGPointMake(self.center.x,self.center.y+liftValue);
[MapPin animateWithDuration:0.1
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateNone;
if(!mapView)
[[NSNotificationCenter defaultCenter] postNotificationName:DPAnnotationViewDidFinishDrag object:nil userInfo:[NSDictionary dictionaryWithObject:self.annotation forKey:DPAnnotationViewKey]];
}];
}];
}
else if (newDragState == MKAnnotationViewDragStateCanceling)
{
// drop the pin and set the state to none

CGPoint endPoint = CGPointMake(self.center.x,self.center.y+liftValue);
[UIView animateWithDuration:0.2
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateNone;
}];
}
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
// When the user touches the view, we need his point so we can calculate by how
// much we should life the annotation, this is so that we don't hide any part of
// the pin when the finger is down.

fingerPoint = point;
return [super hitTest:point withEvent:event];
}

@end

最佳答案

我遇到了同样的问题,尤其是在 iOS 8 下。经过数小时的测试,我相信 iOS 会跟踪它的想法 self.center注释的时间是在状态为 MKAnnotationViewDragStateDragging 期间.如果您制作动画 self.center,则需要格外小心。处理时MKAnnotationViewDragStateEnding .将其读作“我永远无法让它发挥作用”。

相反,我在处理状态时保留了 Daniel 的原始代码 MKAnnotationViewDragStateStartingMKAnnotationViewDragStateCanceling , 我动画 self.center .处理时MKAnnotationViewDragStateEnding我动画 self.transform而不是 self.center .这会维护注释的实际位置,只是改变它的呈现方式。

这对我运行 iOS 7.1 和 iOS 8.0 都很有效。还修复了 hitTest 中的一个错误。 ,并添加了一些代码以在拖动或取消后重新选择注释。我认为这是 MKPinAnnotationView 的默认行为.

- (void)setDragState:(MKAnnotationViewDragState)newDragState animated:(BOOL)animated
{
if(mapView){
id<MKMapViewDelegate> mapDelegate = (id<MKMapViewDelegate>)mapView.delegate;
[mapDelegate mapView:mapView annotationView:self didChangeDragState:newDragState fromOldState:dragState];
}

// Calculate how much to lift the pin, so that it's over the finger, not under.
CGFloat liftValue = -(fingerPoint.y - self.frame.size.height - kFingerSize);

if (newDragState == MKAnnotationViewDragStateStarting)
{
CGPoint endPoint = CGPointMake(self.center.x,self.center.y-liftValue);
[UIView animateWithDuration:0.2
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateDragging;
}];

}
else if (newDragState == MKAnnotationViewDragStateEnding)
{
CGAffineTransform theTransform = CGAffineTransformMakeTranslation(0, -liftValue);
[UIView animateWithDuration:0.2
animations:^{
self.transform = theTransform;
}
completion:^(BOOL finished){
CGAffineTransform theTransform2 = CGAffineTransformMakeTranslation(0, 0);
[UIView animateWithDuration:0.2
animations:^{
self.transform = theTransform2;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateNone;
if(!mapView)
[[NSNotificationCenter defaultCenter] postNotificationName:DPAnnotationViewDidFinishDrag object:nil userInfo:[NSDictionary dictionaryWithObject:self.annotation forKey:DPAnnotationViewKey]];
// Added this to select the annotation after dragging.
// This is the behavior for MKPinAnnotationView
if (mapView)
[mapView selectAnnotation:self.annotation animated:YES];
}];
}];
}
else if (newDragState == MKAnnotationViewDragStateCanceling)
{
// drop the pin and set the state to none
CGPoint endPoint = CGPointMake(self.center.x,self.center.y+liftValue);

[UIView animateWithDuration:0.2
animations:^{
self.center = endPoint;
}
completion:^(BOOL finished){
dragState = MKAnnotationViewDragStateNone;
// Added this to select the annotation after canceling.
// This is the behavior for MKPinAnnotationView
if (mapView)
[mapView selectAnnotation:self.annotation animated:YES];
}];
}
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
// When the user touches the view, we need his point so we can calculate by how
// much we should life the annotation, this is so that we don't hide any part of
// the pin when the finger is down.

// Fixed a bug here. If a touch happened while the annotation view was being dragged
// then it screwed up the animation when the annotation was dropped.
if (dragState == MKAnnotationViewDragStateNone)
{
fingerPoint = point;
}
return [super hitTest:point withEvent:event];
}

关于ios - MKAnnotationView 拖动状态结束动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25324200/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com