objective-c – UIView animateKeyframesWithDuration vs标准动画块动画不同

我最近发现一些UIView动画代码,并注意到它没有使用animateKeyframesWithDuration:delay:options:animations:completion:方法正确,并且一直在尝试修复它,但由于某些原因,动画是不一样的.

这是我发现的代码

view.transform = CGAffineTransformMakeTranslation(300,0);

[UIView animateKeyframesWithDuration:duration/4 delay:delay options:0 animations:^{
    // End
    view.transform = CGAffineTransformMakeTranslation(-10,0);
} completion:^(BOOL finished) {
    [UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
        // End
        view.transform = CGAffineTransformMakeTranslation(5,0);
    } completion:^(BOOL finished) {
        [UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
            // End
            view.transform = CGAffineTransformMakeTranslation(-2,0);
        } completion:^(BOOL finished) {
            [UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
                // End
                view.transform = CGAffineTransformMakeTranslation(0,0);
            } completion:^(BOOL finished) {
            }];
        }];
    }];
}];

这有两个问题:

>应该真正使用关键帧动画,而不是在完成块中嵌套动画.
>当使用animateKeyframesWithDuration:delay:options:animations:completion:你应该调用addKeyframeWithRelativeStartTime:relativeDuration:动画块中的动画:方法.如果你不调用这个方法,那么这个方法的行为就像一个标准的UIView动画块.

See Apple’s documentation regarding this method here.

所以我试图通过正确的方法解决这个问题:

view.transform = CGAffineTransformMakeTranslation(300,0);
double frameDuration = 1.0/4.0; // 4 = number of keyframes

[UIView animateKeyframesWithDuration:duration delay:delay options:0 animations:^{
    [UIView addKeyframeWithRelativeStartTime:0*frameDuration relativeDuration:frameDuration animations:^{
        view.transform = CGAffineTransformMakeTranslation(-10,0);
    }];
    [UIView addKeyframeWithRelativeStartTime:1*frameDuration relativeDuration:frameDuration animations:^{
        view.transform = CGAffineTransformMakeTranslation(5,0);
    }];
    [UIView addKeyframeWithRelativeStartTime:2*frameDuration relativeDuration:frameDuration animations:^{
        view.transform = CGAffineTransformMakeTranslation(-2,0);
    }];
    [UIView addKeyframeWithRelativeStartTime:3*frameDuration relativeDuration:frameDuration animations:^{
        view.transform = CGAffineTransformMakeTranslation(0,0);
    }];
} completion:nil];

我觉得这两个动画都应该是一样的,但是不是这样.我的尝试做错了什么?

编辑:Example project(使用命令T来切换模拟器中的慢速动画)

解决方法

tl; dr:他们可能看起来不同,因为他们做不同的事情,并导致不同的动画被添加到两个视图.不幸的是,我真的不知道如何解决它.

第一版后面发生了什么

正如您已经说过的第一个版本不正确使用API​​.它不使用addKeyframeWithRelativeStartTime添加关键帧:relativeDuration:animations:而是直接在动画块内更改属性.然后,它将在完成块中创建一个新的“关键帧动画”(您将很快看到为什么我使用吓唬报价).

在幕后,这并不会导致CAKeyframeAnimations(虽然我不认为你应该依赖于这个事实).这是我在四个动画对象中添加到项目中的view1后面层中的一些记录. (我被骗了一点,只记录了.m41部分的变换(对应于x的翻译)).

BASIC
keyPath: transform
duration: 0.125
from: 300.0
model value: -10.0
timing: easeInEaSEOut

BASIC
keyPath: transform
duration: 0.125
from: -10.0
model value: 5.0
timing: easeInEaSEOut

BASIC
keyPath: transform
duration: 0.125
from: 5.0
model value: -2.0
timing: easeInEaSEOut

BASIC
keyPath: transform
duration: 0.125
from: -2.0
model value: 0.0
timing: easeInEaSEOut

你可以看到每个动画都有一个fromValue,但是没有tovalue或者byValue.您可以在文档中阅读,这意味着:

fromValue is non-nil. Interpolates between fromValue and the current presentation value of the property.

第二版后面发生了什么

另一方面,向动画正确添加关键帧的第二个版本会导致将此单个CAKeyframeAnimation添加到view2后面的层中. (我仍然只记录.m41部分的变换)

KEYFRAME 
keyPath: transform
duration: 0.500
values: (
    300,-10,5,-2,0
)
keyTimes: (
    0.0,0.25,0.5,0.75,1.0
)
timing: easeInEaSEOut
timings: (nil)
calculationMode: linear

正如你可以看到,它在相同的值之间在相同的时间,但在一个关键帧动画动画.它也具有相同的总持续时间并使用相同的定时功能.

有一件事我不明白.如果我修改真正的关键帧动画(在我重写的addAnimation内部:forKey:在调用super之前)显式地设置定时功能阵列中的定时功能,那么它们看起来完全相同.也就是说,我在关键帧动画添加到图层之前做到这一点.

camediatimingFunction *function = keyFrame.timingFunction;
keyFrame.timingFunction = nil;
keyFrame.timingFunctions = @[function,function,function];

这个伎俩是非常丑陋的,你绝对不应该使用它,除了纯粹的调试之外的事情!

那为什么他们看起来不一样?

那么,我想这个答案与UIKit在第二种情况下创建的关键帧动画的时序函数数组有关.这几乎是我得到的唯一结论.

也就是说,我不知道这是一个bug还是修复它.我只是知道您的项目中的代码实际上在核心动画级别.

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...