如何同步制作UIView和CALayer的动画 [英] How to synchronously animate a UIView and a CALayer

查看:60
本文介绍了如何同步制作UIView和CALayer的动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了说明这个问题,我在Github上注册了一个非常小的Xcode项目(两个类,下载11kb).在此处查看要点,或使用 git clone git@gist.github.com:93982af3b65d2151672e.git .

To illustrate this question, I gisted a very small Xcode project on Github (two classes, 11kb download). Have a look at the gist here or use git clone git@gist.github.com:93982af3b65d2151672e.git.

请考虑以下情况.我的自定义视图称为容器视图" ,其中包含两个小视图方块.在此屏幕截图中说明:

Please consider the following scenario. A custom view of mine, called 'container view', contains two little squares. Illustrated in this screenshot:

蓝色方块是22x22 pt UIView 实例,红色方块是22x22 pt CALayer 实例.出于这个问题的目的,我希望两个正方形粘在"外部视图的右下角,同时为该外部视图的框架设置动画.

The blue square is a 22x22 pt UIView instance and the red square is a 22x22 pt CALayer instance. For purposes of this question I want the two squares to 'stick' to the bottom right corner of the outer view, while I animate the frame of that outer view.

我在 UIView 的类方法 animateWithDuration:delay:options:animations:completion:中更改容器视图的框架,并使用类型为非默认的缓动参数 UIViewAnimationCurveEaseOut .

I change the container view's frame within a UIView's class method animateWithDuration:delay:options:animations:completion:, with a non-default easing parameter of type UIViewAnimationCurveEaseOut.

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

注意:蓝色UIView框架和红色CALayer框架都在容器视图的覆盖的 setFrame:方法中设置,但是如果我已将蓝色的UIView的 autoresizingMask 属性设置为UIView灵活的左边界和上边界.

Note: Both the blue UIView's and the red CALayer's frame are set in the overridden setFrame: method of the container view, but results would have been the same if I had set the blue UIView's autoresizingMask property to UIView flexible left and top margins.

在生成的动画中,蓝色方块按照我的意图粘"在角落,但是红色方块完全忽略了动画的时间安排和放松程度.我认为这是由于Core Animation的隐式动画功能所致,该功能以前曾在许多场合为我提供帮助.

In the resulting animation, the blue square 'sticks' to the corner just the way I intended it, but the red square completely disregards both timing and easing of the animation. I assume this is because of the implicit animation feature of Core Animation, a feature that has helped me in many occasions before.

以下是动画序列中的一些屏幕截图,它们说明了两个正方形的异步性:

Here are a few screenshots in the animation sequence that illustrate the asynchronicity of the two squares:

问题所在:是否有一种方法可以使两个帧更改同步,以使红色的CALayer和蓝色的UIView都以相同的动画持续时间和缓动曲线移动,就好像它们是一个动画一样彼此粘着查看?

P.S.当然,可以通过多种方式实现两个正方形粘合在一起所需的视觉效果,例如,通过使两层都变为 CALayer s或 UIView s,但是真正问题所在的项目很合法,一个原因是CALayer,另一个原因是UIView.

P.S. Of course the required visual result of the two squares sticking together could be achieved in any number of ways, for example by having both layers become either CALayers or UIViews, but the project that the real issue is in has a very legit cause for the one to be a CALayer and the other to be a UIView.

推荐答案

我假设您正确设置了最终位置,并且在动画之后将视图和图层对齐.与动画无关,仅与几何无关.

I'm assuming that you got the end position correct and that after the animation that the view and the layer are aligned. That has nothing to do with the animation, just geometry.

当您更改不是视图层的 CALayer 的属性时(如您的情况),它将隐式地为其新值设置动画.要自定义此动画,可以使用显式动画,例如基本动画.更改基本动画中的帧看起来像这样.

When you change the property of a CALayer that isn't the layer of a view (like in your case) it will implicitly animate to its new value. To customize this animation you could use an explicit animation, like a basic animation. Changing the frame in a basic animation would look something like this.

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"];

如果两个动画的定时功能和持续时间相同,则应保持对齐.

If the timing function and the duration of both animations are the same then they should stay aligned.

还请注意,显式动画不会更改值,并且您必须添加动画并设置新值(如上述示例中一样)

Also note that explicit animations doesn't change the value and hat you have to both add the animation and set the new value (like in the sample above)

是的,有多种方法可以达到相同的效果.一个示例是将视图和图层作为同一子视图的子视图(该子视图又是外部框架的子视图).

Yes, there are a number of ways to achieve the same effect. One example is having the view and the layer be subviews of the same subview (that in turn is a subview of the outer frame).

您不能轻易地将UIView动画与显式动画分组.您都不能使用动画组(因为您将它们应用于不同的图层),但是可以使用CATransaction:

You can't easily group the UIView-animation with an explicit animation. Neither can you use an animation group (since you are applying them to different layers) but yo can use a 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];

这篇关于如何同步制作UIView和CALayer的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆