2013-02-27 2 views
0

Кажется, что я не вижу очевидного при анимации ключевого кадра. Я просмотрел многие примеры кода, включая Apple MoveMe, ссылаясь на документацию CAKeyframeAnimation, но я не могу найти несоответствие, которое может вызвать то, что я вижу.CAKeyframeAnimation не анимация до тех пор, пока я не поверну устройство

Я создаю CGMutablePathRef, затем CAKeyframeAnimation и настроил его для просмотра изображения вдоль пути. Создана анимационная группа, поэтому я могу удалить представление по завершении.

Тем не менее, моя анимация никогда не появляется. Пока я не поворачиваю устройство. Кажется, ретрансляция точки зрения заставляет анимацию кикстарт. Я пробовал это как [theImageView setNeedsDisplay] или даже setNeedsLayout, а также на виде контейнера. Тем не менее, все еще не могу заставить его работать, когда мне нужно. Они появляются только при повороте устройства.

В следующем -cgPathFromArray: принимает NSArray внутренних кодов операций, который преобразуется в CGPathRef. Его проверка правильна, потому что когда я поворачиваю устройство, анимация отображается по запрограммированному пути.

- (void) animateImage: (NSString*) imageName 
       onPath: (NSArray*) path 
     withDuration: (NSString*) duration 
{ 
    if (self.sceneView) 
    { 
     CGMutablePathRef animationPath = [self cgPathFromArray: path]; 

     if (animationPath) 
     { 
      UIImage* image  = [self findImage: imageName]; 

      if (image) 
      { 
       UIImageView* imageView = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, image.size.width, image.size.height)]; 

       if (imageView) 
       { 
        CAKeyframeAnimation* keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath: @"position"]; 

        imageView.image = image; 

        [self.sceneView addSubview: imageView]; 

        keyFrameAnimation.removedOnCompletion = YES; 
        keyFrameAnimation.fillMode    = kCAFillModeForwards; 
        keyFrameAnimation.duration    = duration.floatValue; 
        keyFrameAnimation.timingFunction  = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]; 
        keyFrameAnimation.repeatCount = 0; 

        keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 

        [keyFrameAnimation setPath: animationPath]; 

        //group animation with termination block to cleanup 
        CAAnimationGroup* group  = [CAAnimationGroup animation]; 

        group.duration    = keyFrameAnimation.duration; 
        group.removedOnCompletion = YES; 
        group.fillMode    = kCAFillModeForwards; 
        group.animations   = @[keyFrameAnimation]; 

        CorpsAnimationCompletionBlock theBlock = ^void(void) 
        { 
         [imageView removeFromSuperview]; 
        }; 

        [group setValue: theBlock 
          forKey: kCorpsAnimationCompletionBlock]; 

        group.delegate = self; 

        [imageView.layer addAnimation: group 
              forKey: nil]; 
       } 
      } 
     } 
    } 
} 

Любой может помочь с этим?

ответ

1

Возможно, у вас проблемы, потому что вы добавляете анимацию к слою в той же транзакции, где слой добавляется в видимое дерево слоев. Core Animation не любит прикреплять анимации к слоям, которые еще не были зафиксированы. Вы можете обойти это, выполнив [CATransaction flush] после добавления слоя.

Ваш код довольно сложно просмотреть из-за чрезмерного гнездования. Подумайте об использовании ранних возвратов, чтобы сделать его более читаемым.

Кроме того, вы явно создаете тот же фрейм, который создавал бы для вас инициализатор -[UIImage initWithImage:].

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

Таким образом:

- (void) animateImage:(NSString *)imageName onPath: (NSArray *)path 
    withDuration: (NSString *)duration 
{ 
    if (!self.sceneView) 
     return; 

    CGMutablePathRef animationPath = [self cgPathFromArray:path]; 
    if (!animationPath) 
     return; 

    UIImage *image = [self findImage:imageName]; 
    if (!image) 
     return; 

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 
    [self.sceneView addSubview: imageView]; 

    // commit the implicit transaction so we can add an animation to imageView. 
    [CATransaction flush]; 

    [CATransaction begin]; { 
     [CATransaction setCompletionBlock:^{ 
      [imageView removeFromSuperview]; 
     }]; 

     CAKeyframeAnimation *animation = [CAKeyframeAnimation 
      animationWithKeyPath:@"position"]; 
     animation.duration = duration.floatValue; 
     animation.timingFunction = [CAMediaTimingFunction 
      functionWithName:kCAMediaTimingFunctionLinear]; 
     animation.path = animationPath; 
     [imageView.layer addAnimation:animation forKey:animation.keyPath]; 
    } [CATransaction commit]; 
} 
+0

Простое добавление '[CATransaction вровень];' сделал трюк. Благодаря! (В конце концов, я останусь в своем единственном заявлении о возврате, потому что он принадлежит ;-) –

+0

@ Martin-GillesLavoie, нет, он [не принадлежит]] (http: //softwareengineering.stackexchange. ком/кв/18454/146874)! –