Iphone CABasicAnimation不设置我的属性的动画
我一直在试图理解我的动画有什么问题,但我仍然没有弄明白。我认为这应该是非常直截了当的,但即使在阅读了大量的示例和文档之后,我也可能遗漏了一些东西 我的问题源于这样一个事实:在iPhone上,无法自动调整层的大小(使用视图)。文档中另有说明,但SDK中没有该层的autoresizeMask。所以我决定做一点变通,自己制作图层动画 我有一段简单的代码,可以做一个简单的调整动画。这些值很好,我甚至设置了代理以跟踪动画的开始/结束Iphone CABasicAnimation不设置我的属性的动画,iphone,animation,core-animation,properties,Iphone,Animation,Core Animation,Properties,我一直在试图理解我的动画有什么问题,但我仍然没有弄明白。我认为这应该是非常直截了当的,但即使在阅读了大量的示例和文档之后,我也可能遗漏了一些东西 我的问题源于这样一个事实:在iPhone上,无法自动调整层的大小(使用视图)。文档中另有说明,但SDK中没有该层的autoresizeMask。所以我决定做一点变通,自己制作图层动画 我有一段简单的代码,可以做一个简单的调整动画。这些值很好,我甚至设置了代理以跟踪动画的开始/结束 // I've got a property named layerIm
// 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"];
}
有什么想法吗?(此包含代码的视图是窗口子视图的子视图,如果这可能会产生影响的话)
---编辑---
似乎帧无法通过CABasicAnimation和命名属性“frame”设置动画。当使用边界时,我得到了一些奇怪的结果,但至少我得到了一些东西。将继续对此进行调查。密钥路径应仅为属性的密钥路径,而不是对象的名称 用这个
[CABasicAnimation animationWithKeyPath:@"frame"]
而不是这个
[CABasicAnimation animationWithKeyPath:@"layerImage.frame"]
顺便说一句,当你给一个层添加动画时,关键点并不意味着要设置动画的关键点属性。只有您希望此动画具有的关键点(名称)(这是指代码的最后一行)因此,解决方案是为层的@“边界”和@“位置”设置动画,因为在iPhone上无法为帧设置动画。我花了一些时间才明白,位置是层的中心,边界的大小是从中心延伸的,但这是容易的部分 所以,我在简历中所做的是:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
CABasicAnimation *animation = (CABasicAnimation*)anim;
if ([animation.keyPath isEqualToString:@"bounds"]) {
layerImage.bounds = [animation.toValue CGRectValue];
} else if ([animation.keyPath isEqualToString:@"position"]) {
layerImage.position = [animation.toValue CGPointValue];
}
}
- (void)setFrame:(CGRect)value {
CGRect bounds = CGRectMake(0, 0, value.size.width, value.size.height);
if ([UIView isAnimationStarted]) {
// animate the bounds
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
animation.duration = [UIView animationDuration];
animation.fromValue = [NSValue valueWithCGRect:layerImage.bounds];
animation.toValue = [NSValue valueWithCGRect:bounds];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [UIView animationFunction];
animation.delegate = self;
[layerImage addAnimation:animation forKey:@"BoundsAnimation"];
// animate the position so it stays at 0, 0 of the frame.
animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = [UIView animationDuration];
animation.fromValue = [NSValue valueWithCGPoint:layerImage.position];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(bounds.size.width / 2, bounds.size.height / 2)];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [UIView animationFunction];
animation.delegate = self;
[layerImage addAnimation:animation forKey:@"PositionAnimation"];
} else {
layerImage.frame = bounds;
}
[super setFrame:value];
}
所以,你在这里解决了问题,这很好,但你对自己问题的回答有些不准确。让我纠正几件事: 帧属性可以设置动画,但不能使用显式动画。如果对视图的根层以外的层执行以下操作,则帧的动画效果会很好:
[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
您可能还误解了动画和层之间的区别。将动画添加到层,但将动画添加到层不会自动设置正在设置动画的特性
Calayer是模型对象。它们包含有关最终渲染到屏幕的层的信息。如果希望层的属性实际具有该值,则必须设置该层的属性。如果只是设置属性的动画,它将只是一个视觉表示,而不是实际的-这就是为什么该值会捕捉回层的原始值,因为您从未实际更改过它
这就引出了下一点。你说:
使用“animation.removedOnCompletion”=
否;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"];
你也可以考虑动画分组。使用动画组,可以将多个动画组合在一起,然后控制它们之间的关系。在您的情况下,边界动画和位置动画的持续时间是相同的,因此您尝试在没有组的情况下执行的操作会很好,但是如果您希望偏移动画的开始,例如,您不希望位置动画在帧动画中的一秒或两秒之前开始,可以通过设置位置动画的起始时间值来错开它们
最后,我想知道为什么不能使用UIView上的隐式动画。我在编写的绝大多数核心动画代码中都使用了这些代码,但我不明白为什么这样做不适合您的情况致以最诚挚的问候。对于帧来说是可以的,但是CABasicAnimation如何知道要为该属性设置动画的层?这是否意味着我必须做[layerImage addAnimation:animation…]。(T