代码之家  ›  专栏  ›  技术社区  ›  Ben Zwak

子类化MKAnnotationView并重写setDragState

  •  9
  • Ben Zwak  · 技术社区  · 15 年前

    这是关于使用MKMapKit的iPhone应用程序:

    - (void) movePinUpFinished {
    
         [super setDragState:MKAnnotationViewDragStateDragging];
         [self setDragState:MKAnnotationViewDragStateDragging];
    }
    
    - (void) setDragState:(MKAnnotationViewDragState) myState {
         if (myState == MKAnnotationViewDragStateStarting) {
              NSLog(@"starting");
              CGPoint endPoint = CGPointMake(self.center.x,self.center.y-20);
              self.center = endPoint;
              [self movePinUpFinished];
         }
         if (myState == MKAnnotationViewDragStateEnding) {
              NSLog(@"ending");
              [super setDragState:MKAnnotationViewDragStateEnding];
              [self setDragState:MKAnnotationViewDragStateNone];
              [super setDragState:MKAnnotationViewDragStateNone];
         }
         if (myState == MKAnnotationViewDragStateDragging) {
              NSLog(@"dragging");
         }
         if (myState == MKAnnotationViewDragStateCanceling) {
              NSLog(@"cancel");
         }
         if (myState == MKAnnotationViewDragStateNone) {
              NSLog(@"none");
         }
    }
    

    一切正常,注释向上移动了一点,可以拖动,当我释放注释时,mapview接收到“dragstateending”。

    if (myState == MKAnnotationViewDragStateStarting) {
              NSLog(@"starting");
              CGPoint endPoint = CGPointMake(self.center.x,self.center.y-20);
              [UIView animateWithDuration:1.0
               animations:^{ self.center = endPoint; }
               completion:^(BOOL finished){ [self movePinUpFinished]; }];
         }
    

    动画在一秒钟内按需要运行,注释可以拖动。但是当我释放注释时,mapview没有通过delegat接收结束。我还认识到,当我用“UIView animateWithDuration…”制作动画时,在开始拖动之后,动画开始时,注释的气球会立即打开。当我在没有动画的情况下设置新中心时,气球将保持关闭,并且只有在通过释放注释完成拖动后才打开。

    我做错什么了?这是重写setDragState的正确方法吗。我真的要叫超级班吗?但是没有在超类中设置dragstate,我的mapview就没有意识到dragstate的变化。

    我想知道MKPinAnnotationView的原始实现,但是因为它是一个内部类,所以我找不到setDragState方法的描述。

    谢谢你的帮助。干杯,

    3 回复  |  直到 15 年前
        1
  •  23
  •   William Denniss    13 年前

    我有引脚拖动工作,但试图找出为什么引脚周年纪念发生时,你不覆盖setDragState-不再在我的实现工作。你的问题包含了我的答案。。谢谢!

    下面是我最终得到的代码(在您的帮助下),它按照我预期的方式执行所有的提升、拖动和下降操作。希望这对你也有帮助!

    - (void)setDragState:(MKAnnotationViewDragState)newDragState animated:(BOOL)animated
    {
        if (newDragState == MKAnnotationViewDragStateStarting)
        {
            // lift the pin and set the state to dragging
    
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y-20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
                                 { self.dragState = MKAnnotationViewDragStateDragging; }];
        }
        else if (newDragState == MKAnnotationViewDragStateEnding)
        {
            // save the new location, drop the pin, and set state to none
    
            /* my app specific code to save the new position
            objectObservations[ACTIVE].latitude = pinAnnotation.coordinate.latitude;
            objectObservations[ACTIVE].longitude = pinAnnotation.coordinate.longitude;
            posChanged = TRUE;
            */
    
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y+20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
                                 { self.dragState = MKAnnotationViewDragStateNone; }];
        }
        else if (newDragState == MKAnnotationViewDragStateCanceling)
        {
            // drop the pin and set the state to none
    
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y+20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
                                 { self.dragState = MKAnnotationViewDragStateNone; }];
        }
    }
    
        2
  •  3
  •   Community Mohan Dere    9 年前

    Brian's solution 如果成功的话,它没有考虑到用户手指阻塞正在被操纵的注释视图。

    这意味着用户在拖动pin时无法精确放置pin。标准 MKPinAnnotationView 在这方面做得很好,当手指开始拖动时,销被提升到手指上方,销的可视点用于放置,而不是位于手指下方的先前中心点。

    除此之外,我的实现还添加了另一个动画,当拖动后放下管脚时,通过提升管脚并以更高的速度放下管脚。这与本机用户体验非常接近,您的用户将对此表示赞赏。

    请查看我的 gist on GitHub for the code .

    真正酷的是将委托设置为可选的,当注释视图放回地图上时,可以选择发送通知。

        3
  •  2
  •   JakubM    15 年前

    我没怎么研究本的代码,但它对我不起作用。所以我试了布赖恩的,效果很好。谢谢!很长一段时间以来,我一直在尝试解决拖放过程中注释的动画问题。

    - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState . 这是我的密码:

    DragTableAnnotationView.h:

    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>
    
    @interface DraggableAnnotationView : MKAnnotationView 
    {
        id <MKMapViewDelegate> delegate;
        MKAnnotationViewDragState dragState;
    }
    
    @property (nonatomic, assign) id <MKMapViewDelegate> delegate;
    @property (nonatomic, assign) MKAnnotationViewDragState dragState;
    @property (nonatomic, assign) MKMapView *mapView;
    
    @end
    

    #import "DraggableAnnotationView.h"
    #import "MapAnnotation.h"
    
    @implementation DraggableAnnotationView
    @synthesize delegate, dragState, mapView;
    
    
    
    - (void)setDragState:(MKAnnotationViewDragState)newDragState animated:(BOOL)animated
    {
        [delegate mapView:mapView annotationView:self didChangeDragState:newDragState fromOldState:dragState];
    
        if (newDragState == MKAnnotationViewDragStateStarting) {
            // lift the pin and set the state to dragging
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y-20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
             { dragState = MKAnnotationViewDragStateDragging; }];
        } else if (newDragState == MKAnnotationViewDragStateEnding) {
            // drop the pin, and set state to none
    
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y+20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
             { dragState = MKAnnotationViewDragStateNone; }];
        } else if (newDragState == MKAnnotationViewDragStateCanceling) {
            // drop the pin and set the state to none
    
            CGPoint endPoint = CGPointMake(self.center.x,self.center.y+20);
            [UIView animateWithDuration:0.2
                             animations:^{ self.center = endPoint; }
                             completion:^(BOOL finished)
             { dragState = MKAnnotationViewDragStateNone; }];
        }
    }
    
    - (void)dealloc 
    {
        [super dealloc];
    }
    
    @end