Bezdepbonusu7Программирование: статьи и ответы

Вопрос

CABasicAnimation мерцает при применении завершения

Автор вопроса: Laur StefanОтветов: 2

Я пытаюсь применить анимацию вращения по количеству градусов к UIImageView и сохранить преобразование вращения в блоке завершения.

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

Вот код, который я сейчас использую:

if (futureAngle == currentAngle) {
    return;
}

float rotationAngle;
if (futureAngle < currentAngle) {
    rotationAngle = futureAngle - currentAngle;
}else{
    rotationAngle = futureAngle - currentAngle;
}

float animationDuration = fabs(rotationAngle) / 100;
rotationAngle = GLKMathDegreesToRadians(rotationAngle);

[CATransaction begin];
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.byValue = [NSNumber numberWithFloat:rotationAngle];
rotationAnimation.duration = animationDuration;
rotationAnimation.removedOnCompletion = YES;

[CATransaction setCompletionBlock:^{
    view.transform = CGAffineTransformRotate(view.transform, rotationAngle);
}];

[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
[CATransaction commit];
  • Когда вы говорите мерцание, я полагаю, вы имеете в виду, что в конце анимации она на мгновение возвращается в исходное состояние, прежде чем вернуться в конечное состояние? Это можно решить либо (а) установив окончательный view.transform перед запуском анимации (и вам больше не нужен completionBlock); или (b) установив fillMode анимации на kCAFillModeForwards и установив removedOnCompletion на false. Rob 28.06.2016
  • См. oleb.net/blog/2012/11/prevent-caanimation- snap-back или stackoverflow.com/a/31010421/1271826 или stackoverflow.com/a/7690841/1271826 Rob 28.06.2016
  • @Rob, можете ли вы привести пример предложения относительно блока завершения? Я попробовал fillMode на kCAFillModeForwards и установил для removeOnCompletion значение false перед созданием сообщения, и они у меня не сработали. Laur Stefan 29.06.2016

iosobjective-ccabasicanimationcatransaction

Ответы

Ответ 1 · рейтинг 19 · Rob

Когда вы говорите мерцание, я полагаю, вы имеете в виду, что в конце анимации она на мгновение возвращается в исходное состояние, прежде чем вернуться в конечное состояние? Это можно решить либо путем

  • установка конечного view.transform перед тем, как вы начнете анимацию (и вам больше не нужен completeBlock);
  • установив fillMode анимации на kCAFillModeForwards и установив removedOnCompletion на false.

Лично я считаю, что установка анимированного свойства в его целевое значение до запуска анимации - это самый простой способ сделать это.

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

- (void)rotate:(UIView *)view by:(CGFloat)delta {
    float animationDuration = 2.0;
    CGFloat currentAngle = self.angle;                                                    // retrieve saved angle
    CGFloat nextAngle = self.angle + delta;                                               // increment it
    self.angle = nextAngle;                                                               // save new value

    view.transform = CGAffineTransformMakeRotation(nextAngle);                            // set property to destination rotation

    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];  // now rotate
    rotationAnimation.fromValue = @(currentAngle);
    rotationAnimation.toValue = @(nextAngle);
    rotationAnimation.duration = animationDuration;
    rotationAnimation.removedOnCompletion = YES;
    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

Или, думаю, еще проще, просто настроить transform:

- (void)rotate:(UIView *)view by:(CGFloat)delta {
    float animationDuration = 2.0;
    CGAffineTransform transform = view.transform;                                         // retrieve current transform
    CGAffineTransform nextTransform = CGAffineTransformRotate(transform, delta);          // increment it

    view.transform = nextTransform;                                                       // set property to destination rotation

    CABasicAnimation *rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];             // now rotate
    rotationAnimation.fromValue = [NSValue valueWithCGAffineTransform:transform];
    rotationAnimation.toValue = [NSValue valueWithCGAffineTransform:nextTransform];
    rotationAnimation.duration = animationDuration;
    rotationAnimation.removedOnCompletion = YES;
    [view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

Ответ 2 · рейтинг 3 · Fonix

Я видел мерцание даже при использовании предложенного ответа Роба, но оказалось, что это просто ошибка симулятора. На реальных устройствах я не вижу мерцания, если вы тестировали только на симуляторе, попробуйте на реальном устройстве, если вы не хотите тратить часы своей жизни, как я.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы