CAGradientLayer 属性不在 UIView 动画块内设置动画
我有一种感觉,我忽略了一些基本的东西,但是还有什么比在互联网上出错更好的方法来找到它呢?
我有一个相当基本的用户界面。我的 UIViewController
的视图是一个子类,其 +layerClass
是 CAGradientLayer
。根据用户的操作,我需要移动一些 UI 元素,并更改背景渐变的值。代码看起来像这样:
[UIView animateWithDuration:0.3 animations:^{
self.subview1.frame = CGRectMake(...);
self.subview2.frame = CGRectMake(...);
self.subview2.alpha = 0;
NSArray* newColors = [NSArray arrayWithObjects:
(id)firstColor.CGColor,
(id)secondColor.CGColor,
nil];
[(CAGradientLayer *)self.layer setColors:newColors];
}];
问题是我在这个块中对子视图动画所做的更改很好(东西移动和淡入淡出),但对渐变颜色的更改却没有。它只是交换。
现在,文档确实说动画块中的核心动画代码不会继承该块的属性(持续时间、缓动、 ETC。)。但这是否根本没有定义动画事务? (文档的含义似乎是您将获得默认动画,而我却没有。)
我必须使用显式的 CAAnimation 来完成这项工作吗? (如果是这样,为什么?)
I have a feeling I'm overlooking something elementary, but what better way to find it than to be wrong on the internet?
I have a fairly basic UI. The view for my UIViewController
is a subclass whose +layerClass
is CAGradientLayer
. Depending on the user's actions, I need to move some UI elements around, and change the values of the background's gradient. The code looks something like this:
[UIView animateWithDuration:0.3 animations:^{
self.subview1.frame = CGRectMake(...);
self.subview2.frame = CGRectMake(...);
self.subview2.alpha = 0;
NSArray* newColors = [NSArray arrayWithObjects:
(id)firstColor.CGColor,
(id)secondColor.CGColor,
nil];
[(CAGradientLayer *)self.layer setColors:newColors];
}];
The issue is that the changes I make in this block to the subviews animate just fine (stuff moves and fades), but the change to the gradient's colors does not. It just swaps.
Now, the documentation does say that Core Animation code within an animation block won't inherit the block's properties (duration, easing, etc.). But is it the case that that doesn't define an animation transaction at all? (The implication of the docs seems to be that you'll get a default animation, where I get none.)
Do I have to use explicit CAAnimation
to make this work? (And if so, why?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里似乎发生了两件事。第一个(正如 Travis 正确指出的那样,并且文档指出)是 UIKit 动画似乎对应用于 CALayer 属性更改的隐式动画没有任何影响。我认为这很奇怪(UIKit必须使用核心动画),但事实就是如此。
这是该问题的一个(可能非常愚蠢?)解决方法:
另一个关键是这个渐变层是我的视图层。这意味着我的视图是图层的委托(其中,如果渐变图层只是一个子图层,则它不会有委托)。
-actionForLayer:forKey:
的UIView
实现为"colors"
事件返回NSNull
。 (可能不在特定 UIView 动画列表中的每个事件。)将以下代码添加到我的视图中将导致颜色更改按预期进行动画处理:
There seem to be two things going on here. The first (as Travis correctly points out, and the documentation states) is that UIKit animations don't seem to hold any sway over the implicit animation applied to
CALayer
property changes. I think this is weird (UIKit must be using Core Animation), but it is what it is.Here's a (possibly very dumb?) workaround for that problem:
The other key is that this gradient layer is my view's layer. That means that my view is the layer's delegate (where, if the gradient layer was just a sublayer, it wouldn't have a delegate). And the
UIView
implementation of-actionForLayer:forKey:
returnsNSNull
for the"colors"
event. (Probably every event that isn't on a specific list of UIView animations.)Adding the following code to my view will cause the color change to be animated as expected:
您必须使用显式 CAAnimations,因为您正在更改 CALayer 的值。
UIViewAnimations 适用于 UIView 属性,但不能直接适用于其 CALayer 属性...
实际上,您应该使用 CABasicAnimation,以便可以访问其
fromValue
和toValue
属性。以下代码应该适合您:
CAAnimations 有一个技巧,您必须在完成动画后显式设置属性的值。
您可以通过设置委托来完成此操作,在本例中,我将其设置为调用动画的对象,然后重写其
animationDidStop:finished:
方法以将 CAGradientLayer 颜色的设置包含为其最终值。您还必须在
animationDidStop:
方法中进行一些转换,才能访问动画的属性。You have to use explicit CAAnimations, because you're changing the value of a CALayer.
UIViewAnimations work on UIView properties, but not directly on their CALayer's properties...
Actually, you should use a CABasicAnimation so that you can access its
fromValue
andtoValue
properties.The following code should work for you:
There is a trick with CAAnimations in that you HAVE to explicitly set the value of the property AFTER you complete the animation.
You do this by setting the delegate, in this case I set it to the object which calls the animation, and then override its
animationDidStop:finished:
method to include the setting of the CAGradientLayer's colors to their final value.You'll also have to do a bit of casting in the
animationDidStop:
method, to access the properties of the animation.