iOS animateWithDuration立即完成隐藏/显示甚至不透明度

时间:2014-10-26 17:17:23

标签: ios core-animation

我想让我的CALayer动画显示一段时间,然后淡出,这是我的代码

[_msgLayer removeAllAnimations];
[UIView animateWithDuration:10 delay:0 options:0 animations:^ {
     _msgLayer.hidden = false;
    NSLog(@"showing");
} completion:^(BOOL finished) {
    NSLog(@"showing done, finished=%d", finished);
    [UIView animateWithDuration:10 delay:40 options:0 animations:^ {
        _msgLayer.hidden = true;
    } completion:^(BOOL hideFinished) {
        NSLog(@"hiding done, finished=%d", hideFinished);
    }];
}];

然而,动画根本没有像我预期的那样工作,一切都几乎立即完成

2014-10-26 10:11:28.249 Foobar[91761:6827358] showing
2014-10-26 10:11:28.254 Foobar[91761:6827358] showing done, finished=1
2014-10-26 10:11:28.255 Foobar[91761:6827358] hiding done, finished=1

我看到一些类似的问题,有些人说hidden不可动画,但文档说它可以动画。我也尝试opacity,然后同样的结果,动画仍然立即完成。这是为什么?我该如何解决?

_msgLayer是我自己的类继承CALayer,它有自己的绘图方法。这个动画是从网络事件调用的,就像服务器向iPhone发送消息一样,然后我在屏幕上显示消息。

2 个答案:

答案 0 :(得分:6)

问题在于UIView动画用于动画视图。

使用UIView动画时发生的事情的高概述是块被执行,这会更改视图的属性,而视图的属性又会更改背景层(或直接更改图层属性)。当(支持)图层的属性发生更改时,它会询问其委托(如果图层正在支持视图,则始终是视图)以为该动画提供操作。然后,视图可以检查更改是否发生在动画块内部。如果更改发生在动画块内,则视图将返回具有正确持续时间,时序曲线等的动画。

但是,对于没有附加到图层的视图,没有代理可以询问。相反,该层继续寻找"动作" (动画的更通用术语),最终选择该图层类的默认动作。 CALayer上的the documentation for the -actionForKey:方法概述了此行为。

默认操作几乎总是(路径的动画是一个例外)0.25秒长的基本动画。这是你看到的动画。图层实际上默认为其更改设置动画(它是一种禁用此功能的视图行为),因此您可以从动画块内的更改和动画块外部的形式看到此动画。


如果您想了解更多相关信息:

my objc.io article here的前三分之一更详细地解释了视图与图层之间的交互。我还有a blog post here,其中包括解释隐式动画和显式动画之间的区别。


上面解释了为什么您看到了这种行为。要修复"你可以去更高的抽象并使用视图而不是图层,或者你自己创建动画对象并将它们添加到图层(UIKit在视图级别进行的工作)。

答案 1 :(得分:1)

探索核心动画和堆栈溢出,您应该尝试使用2层来帮助您淡入和淡出。我试图解决类似的问题,下面的答案可以帮助我。

小代码示例:

此代码基于this回答。

CALayer *parentLayer = [CALayer layer];
CALayer *animtingLayer = [CALayer layer];

//FADE IN
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        animation.beginTime = CMTimeGetSeconds(img.startTime);
        animation.duration = CMTimeGetSeconds(_timeline.transitionDuration);
        animation.fromValue = [NSNumber numberWithFloat:0.0f];
        animation.toValue = [NSNumber numberWithFloat:1.0f];
        animation.removedOnCompletion = NO;
        animation.fillMode = kCAFillModeBoth;
        animation.additive = NO;
        [parentLayer addAnimation:animation forKey:@"opacityIN"];

//FADE OUT
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        animation.beginTime = CMTimeGetSeconds(CMTimeAdd(img.passTimeRange.start, img.passTimeRange.duration));
        animation.duration = CMTimeGetSeconds(_timeline.transitionDuration);
        animation.fromValue = [NSNumber numberWithFloat:1.0f];
        animation.toValue = [NSNumber numberWithFloat:0.0f];
        animation.removedOnCompletion = NO;
        animation.fillMode = kCAFillModeBoth;
        animation.additive = NO;
        [animtingLayer addAnimation:animation forKey:@"opacityOUT"];

    [parentLayer addSublayer:animtingLayer];