Создание подклассов MKAnnotationView и переопределение setDragState - PullRequest
9 голосов
/ 09 сентября 2010

Это приложение для iPhone, использующее MKMapKit:

Я создал собственный MKAnnotationView для перетаскиваемой аннотации. Я хочу создать собственную анимацию. Я установил пользовательское изображение булавки, и примечание перетаскивается (что не показано здесь, это происходит в просмотре карты) со следующим кодом:

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

Все работает нормально, аннотация немного перемещается вверх, перетаскивается, и когда я выпускаю аннотацию, представление карты получает "dragstateending".

Но теперь я хочу, чтобы анимация работала в течение определенного периода времени и изменила dragStateStarting на следующее:

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

Анимации запускаются как угодно в течение секунды, и примечание можно перетаскивать. Но когда я выпускаю аннотацию, просмотр карты не получает окончание через делегат. Я также узнал, что, когда я делаю анимацию с «UIView animateWithDuration ...», это то, что сразу после начала перетаскивания, когда анимация начинается, открывается шарик аннотации. Когда я устанавливаю новый центр без анимации, воздушный шар остается закрытым и открывается только после завершения перетаскивания, выпуская аннотацию.

Что я делаю не так? Это правильный способ переопределить setDragState. Мне действительно нужно позвонить в супер класс? Но без установки dragstate в суперклассе мой картограф не осознал изменения dragstate.

Меня интересует первоначальная реализация MKPinAnnotationView, но, поскольку это внутренний класс, я не смог найти описание метода setDragState.

Спасибо за помощь. Cheers,

Ben

Ответы [ 3 ]

23 голосов
/ 16 декабря 2010

У меня работало перетаскивание булавки, но я пытался выяснить, почему анимации штифтов, возникающие, когда вы не переопределяете setDragState, больше не работают в моей реализации. Ваш вопрос содержал мой ответ .. Спасибо!

Часть проблемы с вашим кодом заключается в том, что после того, как вы переопределите функцию setDragState, согласно документации по xcode, вы несете ответственность за обновление переменной dragState в зависимости от поступающего нового состояния. Я также был бы немного обеспокоен вашим кодом вызывая себя (вызов setDragState [self 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; }];
    }
}
3 голосов
/ 27 сентября 2012

В то время как решение Брайана работало, в нем не учитывался палец пользователя, блокирующий представление аннотации, которым манипулируют.

Это означает, что пользователь не мог точно разместить штифт, как толькотащил это.Стандарт MKPinAnnotationView отлично справляется с этим, что происходит, когда палец начинает перетаскивать палец, штифт поднимается над пальцем, а визуальная точка штифта используется для размещения не предыдущей центральной точки, которая теперь находится подfinger.

В дополнение к этому моя реализация также добавляет еще одну анимацию при отбрасывании булавки после перетаскивания, поднимая булавку и сбрасывая ее с более высокой скоростью.Это очень близко к привычному пользовательскому интерфейсу и будет оценено вашими пользователями.

Пожалуйста, ознакомьтесь с моим списком на GitHub для кода .

Что действительно круто, так этоустановка делегата необязательна, при необходимости уведомление отправляется, когда вид аннотации возвращается на карту.

2 голосов
/ 19 января 2011

Я мало изучал код Бена, но он не работал для меня.Так что я попробовал Брайана, и это прекрасно работает.Большое спасибо!Я давно пытаюсь решить анимацию аннотации во время перетаскивания.

Но у меня есть одно предложение к решению Брайана.Я думаю, что было бы лучше поддержать делегата MKMapKit и уведомить его об изменении dragState и сохранить новую позицию в методе стандартного делегата: - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState.Мой код:

DraggableAnnotationView.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

DraggableAnnotationView.m:

#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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...