因此,您已经在这里解决了问题,但您对自己问题的回答有些不准确。让我纠正一些事情:
frame 属性可以设置动画——只是不能使用显式动画。如果您对视图的根层以外的层执行以下操作,则框架的动画效果会很好:
[CATransaction begin];
[CATransaction setAnimationDuration:2.0f];
[animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[CATransaction commit];
请记住,在图层上设置属性会默认为该属性更改设置动画。事实上,如果您不希望属性更改动画,则必须禁用动画。 (当然,只有在为视图的根层以外的层设置动画时才适用。)如果您需要使用显式动画,则对位置和边界进行动画处理是正确的。
您可以使用隐式动画为 UIView 上的框架设置动画:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:3.0f];
[[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)];
[UIView commitAnimations];
这将从视图的当前帧(边界和位置)动画到 x = 45.0、y = 45.0、w = 100.0、h = 100.0。
您似乎也误解了动画和图层之间的区别。您向图层添加动画,但向图层添加动画不会自动设置您正在制作动画的属性。
CALayers 是模型对象。它们包含有关最终渲染到屏幕的图层的信息。如果您希望该属性实际具有该值,您必须设置该图层的属性。如果您只是简单地为属性设置动画,则它只是一种视觉表示,而不是实际的——也就是说,这就是为什么值会突然恢复到图层的原始值,因为您实际上从未更改过它。
这将我引向下一点。你说:
使用“动画.removedOnCompletion =
不;动画.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"];
您可能还需要考虑动画分组。使用动画组,您可以将多个动画组合在一起,然后控制它们相互关联的方式。在您的情况下,您的边界和位置动画的持续时间是相同的,因此您尝试做的事情在没有组的情况下可以正常工作,但是如果您想偏移动画的开始,例如您不想要位置动画开始直到一两秒进入帧动画,您可以通过设置位置动画的 beginTime 值来错开它们。
最后,我很想知道为什么你不能使用 UIView 上可用的隐式动画。我在编写的绝大多数核心动画代码中都使用了这些,但不明白为什么这不适用于您的情况。
最好的问候。