CABasicAnimation not animating my property

Sau*_*eil 8 iphone animation core-animation properties

I've been trying to understand what is wrong with my animation and I still haven't figure it out. I think it should be really straight forward, but there is probably something I'm missing, even after reading lot of examples and documentation.

My problem comes originally form the fact that on the iPhone, you cannot resize layers automatically (with the view). The documentation says otherwise but there is no autoresizeMask for the layer in the SDKs. So I decided to make a little workaround and animate the layer myself.

我有这个简单的代码片段应该做一个简单的调整大小动画.值很好,我甚至设置了委托,以便跟踪动画的开始/结束.

// I've got a property named layerImage (which is a CALayer)
- (void)animateTestWithFrame:(CGRect)value {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"layerImage.frame"];
    animation.duration = 1;
    animation.fromValue = [NSValue valueWithCGRect:self.frame];
    animation.toValue = [NSValue valueWithCGRect:value];
    animation.removedOnCompletion = YES;
    animation.delegate = self;

    [self.layer addAnimation:animation forKey:@"layerImage.frame"];
}
Run Code Online (Sandbox Code Playgroud)

那么,有什么想法吗?(这个包含代码的视图是窗口子视图的子视图,如果这可能有所不同)

---编辑---

似乎框架不能通过CABasicAnimation和命名属性"frame"来设置动画.当使用边界时,我得到了一些奇怪的结果,但至少我得到了一些东西.将继续调查此事.

Mat*_*ong 26

所以你在这里找到了解决方案是件好事,但你对自己问题的回答有些不准确.让我纠正一些事情:

frame属性可以设置动画 - 只是没有显式动画.如果对视图的根层以外的其他图层执行以下操作,则框架将生成动画:

[CATransaction begin];
[CATransaction setAnimationDuration:2.0f];
[animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[CATransaction commit];
Run Code Online (Sandbox Code Playgroud)

请记住,默认情况下,在图层上设置属性会为该属性更改设置动画.实际上,如果您不希望动画更改,则必须禁用属性更改上的动画.(当然,只有在动画视图的根层以外的图层时才会出现这种情况.)如果需要使用显式动画,则在设置位置和边界的动画时是正确的.

可以使用隐式动画在UIView上为框架设置动画:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3.0f];
[[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)];
[UIView commitAnimations];
Run Code Online (Sandbox Code Playgroud)

这将从视图的当前帧(边界和位置)动画到x = 45.0,y = 45.0,w = 100.0,h = 100.0.

看起来你可能也误解了动画和图层之间的区别.您可以向图层添加动画,但向图层添加动画不会自动设置您正在设置动画的属性.

CALayers是模型对象.它们包含有关最终呈现到屏幕的图层的信息.你必须,如果你想要的属性,实际上有值设置图层的属性.如果你只是为属性设置动画,那么它只是一个直观的表示,而不是实际的 - 也就是说这就是为什么值会快速回到图层的原始值,因为你从未真正改变它.

这让我想到了下一点.你说:

使用"animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards;" 确保在动画结束时不重置值

这不完全正确.这两个值只是使动画在视觉上保持在最终位置,但是图层的实际值没有改变.它们仍然是您启动动画时的完全相同的值.通常(除了少数例外)您不想使用这两个参数,因为它们只是可视化的.你想要的是实际设置你动画属性的图层值.

例如,假设您要使用显式动画为图层的位置设置动画.这是您想要的代码:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
[animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]];
[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]];
[animation setDuration:2.0f];

// Actually set the position on the *layer* that you want it to be
// when the animation finishes.
[animationLayer setPosition:CGPointMake(150.0f, 150.0f)];

// Add the animation for the position key to ensure that you
// override the animation for position changes with your animation.
[animationLayer addAnimation:animation forKey:@"position"];
Run Code Online (Sandbox Code Playgroud)

您可能还想考虑动画分组.使用动画组,您可以将多个动画组合在一起,然后控制它们之间的相互关系.在你的情况下,你的边界和位置动画的持续时间是相同的,所以你想要做的事情将没有一个组正常工作,但如果你想要抵消动画的开始,例如你不想要的位置动画开始直到帧动画中的第二个或第二个,您可以通过设置位置动画的beginTime值来错开它们.

最后,我很想知道为什么你不能使用UIView上可用的隐式动画.我在我编写的绝大多数Core Animation代码中都使用了这些代码,并且无法理解为什么这对你的情况不起作用.

最好的祝福.