如何同步动画一个UIView和CALayer的(How to synchronously anima

2019-07-29 15:30发布

为了说明这个问题,我gisted在Github上一个非常小的Xcode项目(两班,11KB下载)。 看看这里的要点或使用git克隆git@gist.github.com:93982af3b65d2151672e.git。


请考虑以下情形。 我的一个自定义视图,称为“容器视图” ,包含两个小广场。 在所示这个截图:

蓝色方块是一个22×22磅UIView实例和红场PT一22×22 CALayer实例。 对于这个问题的目的,我想这两个广场,以“大棒”,以外观图的右下角,而我是动画外视图的框架。

我改变容器视图的一个内帧UIView的类方法animateWithDuration:delay:options:animations:completion:与类型的非默认参数宽松UIViewAnimationCurveEaseOut

[UIView animateWithDuration:1.0 delay:0 
                    options:UIViewAnimationCurveEaseOut 
                 animations:^{ _containerView.frame = randomFrame; } 
                 completion:nil];

注意:两个蓝色的UIView的,红色的CALayer的框架中重写设置setFrame:容器视图的方法,但结果将是相同的,如果我已成立了蓝色的UIView的autoresizingMask属性的UIView灵活的左侧和顶部边缘。

在生成的动画中,蓝方“棍棒”墙角现在的样子我预期的,但红方完全忽视动画的定时和宽松。 我想这是因为核心动画,以前已经帮我在很多场合功能的隐式动画功能。

下面是动画序列几张截图是说明了两个正方形的异步性:

对这个问题: 有没有办法使红色的CALayer和UIView的蓝色都具有相同的动画持续时间和缓和曲线移动,相互粘在一起,好像他们是一个以同步两个框架的变化?

PS当然,两个正方形粘在一起所需的视觉结果,可以在任何数量的方式具有两层成为既可以实现,例如CALayer S或UIView S,但真正的问题是在项目中有一个非常合法的原因对于一个要一个CALayer的,另一个是一个UIView。

Answer 1:

我假设你有正确的,而且,视图和层对齐动画后结束位置。 这已无关的动画,只是形状。


当您更改的属性CALayer 这不是一个视图层 (如你的情况),它会隐式动画到新的价值。 要自定义此动画,你可以使用一个明确的动画,就像一个基本的动画。 在一个基本的动画改变帧会是这个样子。

CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
[myAnimation setToValue:[NSValue valueWithCGRect:myNewFrame]];
[myAnimation setFromValue:[NSValue valueWithCGRect:[myLayer frame]]];
[myAnimation setDuration:1.0];
[myAnimation setTimingFunction:[CAMediaTimingFuntion functionWithName: kCAMediaTimingFunctionEaseOut]];

[myLayer setFrame:myNewFrame];
[myLayer addAnimation:myAnimation forKey:@"someKeyForMyAnimation"];

如果定时功能和两个动画的持续时间相同,则他们应该保持一致。

还要注意的是明确的动画不改变价值和帽子,你必须既能补充动画,并设置新的值(比如在样品上面)


是的,有许多方法来达到同样的效果。 一个实例是具有视图和层是相同的子视图的子视图(其又是外框的子视图)。

编辑

你不能轻易使用显式动画组UIView的动画。 你也不能使用动画组(因为你是它们适用于不同的层),但是哟可以使用CATransaction:

[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFuntion functionWithName: kCAMediaTimingFunctionEaseOut]];

// Layer animation
CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
[myAnimation setToValue:[NSValue valueWithCGRect:myNewFrame]];
[myAnimation setFromValue:[NSValue valueWithCGRect:[myLayer frame]]];

[myLayer setFrame:myNewFrame];
[myLayer addAnimation:myAnimation forKey:@"someKeyForMyAnimation"];

// Outer animation
CABasicAnimation *outerAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
[outerAnimation setToValue:[NSValue valueWithCGRect:myNewOuterFrame]];
[outerAnimation setFromValue:[NSValue valueWithCGRect:[outerView frame]]];

[[outerView layer] setFrame:myNewOuterFrame];
[[outerView layer] addAnimation:outerAnimation forKey:@"someKeyForMyOuterAnimation"];

[CATransaction commit];


Answer 2:

如果你想大卫Rönnqvist在雨燕3.0片断,在这里你有它:

    CATransaction.begin()
    CATransaction.setAnimationDuration(1.0)
    CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut))

    // Layer animation
    let myAnimation = CABasicAnimation(keyPath: "frame");
    myAnimation.toValue = NSValue(cgRect: myNewFrame)
    myAnimation.fromValue = NSValue(cgRect: myLayer.frame)

    myLayer.frame = myNewFrame
    myLayer.add(myAnimation, forKey: "someKeyForMyAnimation")

    // Outer animation
    let outerAnimation = CABasicAnimation(keyPath: "frame")
    outerAnimation.toValue = NSValue(cgRect: myNewOuterFrame)
    outerAnimation.fromValue = NSValue(cgRect: outerView.frame)

    outerView.layer.frame = myNewOuterFrame
    outerView.layer.add(outerAnimation, forKey: "someKeyForMyOuterAnimation")

    CATransaction.commit()


文章来源: How to synchronously animate a UIView and a CALayer