Создание плавного анимирования входа, выхода и обмена двумя изображениями - PullRequest
3 голосов
/ 13 ноября 2010

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

Для этого я сохраняю две переменные экземпляра UIImageView и заменяю self.fishViewCurrent на self.fishViewNext после завершения анимации (см. Код ниже).

Моя проблема в том, что пользователь быстро нажимает на новые ячейки таблицы до того, как появится следующая рыба. Мое быстрое решение состоит в том, чтобы отложить новое сообщение, которое добавит рыбу и просто ничего не делает в данный момент. Это работает для 2 быстрых прикосновений, но не более. Я ищу идеи, если кто-нибудь знает, как я могу улучшить приведенный ниже код, чтобы анимация была плавной, и вы могли нажимать на все, пока последнее отображаемое изображение было последним. Вот важные методы:

Создание первого вида изображения:

- (void) createFish {

self.fishViewCurrent = [[[UIImageView alloc] init] autorelease];
self.fishViewCurrent.contentMode = UIViewContentModeScaleAspectFit;
self.fishViewCurrent.bounds = CGRectMake(0.0f, 0.0f, kFishWidth, kFishHeight);
self.fishViewCurrent.center = CGPointMake(-kFishWidth, kFishYPos); // off the screen to the left
[self addSubview:self.fishViewCurrent];

}

Открытый метод, вызываемый при выборе ячейки таблицы:

- (void) addFish:(UIImage *)fish {

if (self.fishViewNext) {
    [self performSelector:@selector(addFish:) withObject:(UIImage *)fish afterDelay:1.0];
    return;
}
self.fishViewNext = [[[UIImageView alloc] initWithImage:fish] autorelease];
self.fishViewNext.contentMode = UIViewContentModeScaleAspectFit;
self.fishViewNext.bounds = CGRectMake(0.0f, 0.0f, kFishWidth, kFishHeight);
self.fishViewNext.center = CGPointMake(self.bounds.size.width + kFishWidth, kFishYPos);  // off the screen right
[self addSubview:self.fishViewNext];

[UIView beginAnimations:@"swimFish" context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES]; 
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(fishSwamOffHandler:finished:context:)];
[UIView setAnimationRepeatAutoreverses:NO];

self.fishViewNext.center = CGPointMake(self.center.x, kFishYPos); // center
self.fishViewCurrent.center = CGPointMake(-kFishWidth, kFishYPos);  // exit stage left

[UIView commitAnimations];   
}

Обработчик для переключения «следующей» рыбы (UIImageView) на «текущий»:

- (void)fishSwamOffHandler:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {

[self.fishViewCurrent removeFromSuperview]; 
self.fishViewCurrent = self.fishViewNext;
self.fishViewNext = nil;
}

1 Ответ

1 голос
/ 09 декабря 2010

Проще всего было бы создать BOOL ivar, скажем _fishIsSwimming, и _queuedFishView, а затем изменить начало addFish: чтобы оно выглядело так:

- (void) addFish:(UIImage *)fish 
{
    // queue the most recent fish, if one was passed in
    if(fish)    
        self.queuedFishView = [[[UIImageView alloc] initWithImage:fish] autorelease];

    // If something is swimming, leave now
    if(_fishIsSwimming)
        return;

    // If we get here and there's no queued fish, leave now
    if(!self.queuedFishView)
        return;

    // We have a queued fish and nothing is swimming, so do the queued fish next 
    // and clear the queued fish
    _fishIsSwimming = YES;
    self.nextFishView = self.queuedFishView;
    self.queuedFishView = nil;
    // Then carry on as normal
}

Затем в обратном вызове завершения анимации вы делаете это:

-(void) fishSwamOffHandler:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context 
{
    // We're done animating, so ready to do another swimming fish
    _fishIsSwimming = NO;

    [self.fishViewCurrent removeFromSuperview]; 
    self.fishViewCurrent = self.fishViewNext;
    self.fishViewNext = nil;

    // now call to add another fish with nil, so that it will use 
    // the queued fish if there is one and otherwise just early out
    [self addFish:nil];    
}    

Итак, что будет происходить, так это то, что вы всегда будете поддерживать самую последнюю переданную рыбу в queuedFishView, а затем, как только анимация закончится, вы можете вернуться в addFish, и если есть рыба, ожидающая выхода, вы Отправь это. Если нет, просто дождитесь следующего сообщения, нажав кнопку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...