【问题标题】:CABasicAnimation flicker when applying the completion应用补全时 CABasicAnimation 闪烁
【发布时间】:2016-06-28 16:07:11
【问题描述】:

我正在尝试将旋转动画按度数应用于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];

【问题讨论】:

  • 当您说闪烁时,我假设您的意思是在动画结束时,它会在返回最终状态之前暂时返回初始状态?这可以通过以下两种方式解决:(a) 在开始动画之前设置最终的view.transform(并且您不再需要completionBlock);或 (b) 将动画的 fillMode 设置为 kCAFillModeForwards 并将 removedOnCompletion 设置为 false
  • @Rob 你能提供一个关于完成块的建议的例子吗?在创建帖子之前,我尝试将 fillMode 设置为 kCAFillModeForwards 并将 removedOnCompletion 设置为 false,但它们对我不起作用。

标签: ios objective-c cabasicanimation catransaction


【解决方案1】:

当您说闪烁时,我假设您的意思是在动画结束时,它会在返回最终状态之前暂时返回初始状态?这可以通过

来解决
  • 在开始动画之前设置最终的view.transform(并且不再需要completionBlock);
  • 通过将动画的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"];
}

【讨论】:

  • 令人着迷,似乎 如果您尝试同时执行 UIView.animate(例如,只是移动约束),“fillMode 方法”似乎成为答案............
  • 谢谢罗伯!不知何故,第一个选项对我不起作用,但第二个可以。
【解决方案2】:

即使使用 Rob 建议的答案,我也看到闪烁,但事实证明这似乎只是一个模拟器错误。在真实设备上我看不到闪烁,如果您只是在模拟器上进行测试,请在真实设备上尝试,除非您想像我一样浪费生命中的几个小时。

【讨论】:

  • 天哪,你真的为我节省了大量时间。在模拟器上动画闪烁/闪烁,但在真实设备上它只是工作。我花了一段时间才意识到我的代码可能没有问题,而解决方案就在其他地方。非常非常感谢!
猜你喜欢
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多