ios 带有自动反转功能的 UIView 动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5040494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIView animations with autoreverse
提问by Stultus
I have a problem with the setting UIViewAnimationOptionAutoReverse
.
Here is my code.
我的设置有问题UIViewAnimationOptionAutoReverse
。这是我的代码。
CALayer *aniLayer = act.viewToChange.layer;
[UIView animateWithDuration:2.0 delay:1.0 options:(UIViewAnimationCurveLinear | UIViewAnimationOptionAutoreverse) animations:^{
viewToAnimate.frame = GCRectMake(1,1,100,100);
[aniLayer setValue:[NSNumber numberWithFloat:degreesToRadians(34)] forKeyPath:@"transform.rotation"];
} completion:nil ];
The problem is that, after the animation has reversed, the view jumps back to the frame set in the animation block. I want the view to grow and "ungrow" and stop at its original position.
问题是,在动画反转后,视图会跳回到动画块中设置的帧。我希望视图增长和“不增长”并停止在其原始位置。
Is there a solution without programming two consecutive animations?
有没有不用编程两个连续动画的解决方案?
回答by BJ Homer
You have three options.
你有三个选择。
When you use the -[UIView animateWithDuration:…]
methods, the changes you make in the animations
block are applied immediately to the views in question. However, there is also an implicit CAAnimation
applied to the view that animates from the old value to the new value. When a CAAnimation
is active on a view, it changes the displayedview, but does not change the actual properties of the view.
当您使用这些-[UIView animateWithDuration:…]
方法时,您在animations
块中所做的更改会立即应用于相关视图。但是,还有一个隐式CAAnimation
应用于视图,从旧值动画到新值。当 aCAAnimation
在视图上处于活动状态时,它会更改显示的视图,但不会更改视图的实际属性。
For example, if you do this:
例如,如果您这样做:
NSLog(@"old center: %@", NSStringFromCGPoint(someView.center));
[UIView animateWithDuration:2.0 animations: ^{ someView.center = newPoint; }];
NSLog(@"new center: %@", NSStringFromCGPoint(someView.center));
you will see that 'old center' and 'new center' are different; new center will immediatelyreflect the values of newPoint. However, the CAAnimation
that was implicitly created will cause the view to still be displayedat the old center and smoothly move its way to the new center. When the animation finishes, it is removed from the view and you switch back to just seeing the actual model values.
你会看到“旧中心”和“新中心”是不同的;new center 将立即反映 newPoint 的值。但是,CAAnimation
隐式创建的 将导致视图仍然显示在旧中心并平滑地移动到新中心。动画完成后,它会从视图中移除,您可以切换回仅查看实际模型值。
When you pass UIViewAnimationOptionAutoreverse
, it affects the implicitly created CAAnimation
, but does NOT affect the actual change you're making to the values. That is, if our example above had the UIViewAnimationOptionAutoreverse
defined, then the implicitly created CAAnimation
would animate from oldCenter to newCenter and back. The animation would then be removed, and we'd switch back to seeing the values we set… which is still at the new position.
当您通过时UIViewAnimationOptionAutoreverse
,它会影响隐式创建的CAAnimation
,但不会影响您对值所做的实际更改。也就是说,如果我们上面的例子有UIViewAnimationOptionAutoreverse
定义的,那么隐式创建的CAAnimation
将动画从 oldCenter 到 newCenter 并返回。然后动画将被移除,我们将切换回查看我们设置的值......它仍然在新位置。
As I said, there are three ways to deal with this. The first is to add a completion block on the animation to reverse it, like so:
正如我所说,有三种方法可以解决这个问题。第一种是在动画上添加一个完成块来反转它,如下所示:
First Option
第一个选项
CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
animations: ^{ someView.center = newPoint; }
completion:
^(BOOL finished) {
[UIView animateWithDuration:2.0
animations:^{ someView.center = oldCenter; }];
}];
Second Option
第二种选择
The second option is to autoreverse the animation like you're doing, and set the view back to its original position in a completion block:
第二个选项是像您一样自动反转动画,并将视图设置回完成块中的原始位置:
CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
delay:0
options: UIViewAnimationOptionAutoreverse
animations: ^{ someView.center = newPoint; }
completion: ^(BOOL finished) { someView.center = oldCenter; }];
However, this may cause flickering between the time that the animation autoreverse completes and when the completion block runs, so it's probably not your best choice.
但是,这可能会导致动画自动反转完成时间和完成块运行时间之间出现闪烁,因此这可能不是您的最佳选择。
Third Option
第三个选项
The last option is to simply create a CAAnimation
directly. When you don't actually want to change the final value of the property you're changing, this is often simpler.
最后一个选项是直接创建一个CAAnimation
。当您实际上不想更改要更改的属性的最终值时,这通常更简单。
#import <QuartzCore/QuartzCore.h>
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.autoreverses = YES;
animation.repeatCount = 1; // Play it just once, and then reverse it
animation.toValue = [NSValue valueWithCGPoint:newPoint];
[someView.layer addAnimation:animation forKey:nil];
Note that the CAAnimation
way of doing things never changes the actual values of the view; it just masks the actual values with an animation. The view still thinks it's in the original location. (This means, for example, that if your view responds to touch events, it will still be watching for those touch events to happen at the original location. The animation onlychanges the way the view draws; nothing else.
请注意,CAAnimation
做事的方式永远不会改变视图的实际值;它只是用动画掩盖了实际值。视图仍然认为它在原始位置。(这意味着,例如,如果您的视图响应触摸事件,它仍然会在原始位置监视这些触摸事件。动画只会改变视图的绘制方式;没有别的。
The CAAnimation
way also requires that you add it to the view's underlying CALayer
. If this scares you, feel free to use the -[UIView animateWithDuration:…]
methods instead. There's additional functionality available by using CAAnimation
, but if it's something you're not familiar with, chaining UIView animations or resetting it in the completion block is perfectly acceptable. In fact, that's one of the main purposes of the completion block.
该CAAnimation
方法还要求您将其添加到视图的基础CALayer
. 如果这让您感到害怕,请随意使用这些-[UIView animateWithDuration:…]
方法。使用 可以使用其他功能CAAnimation
,但如果您不熟悉它,链接 UIView 动画或在完成块中重置它是完全可以接受的。事实上,这是完成块的主要目的之一。
So, there you go. Three different ways to reverse an animation and keep the original value. Enjoy!
所以,你去了。反转动画并保持原始值的三种不同方法。享受!
回答by Rudolf Adamkovi?
Here's my solution. For 2x repeat, animate 1.5x and do the last 0.5x part by yourself:
这是我的解决方案。对于 2x 重复,动画 1.5x 并自己完成最后 0.5x 部分:
[UIView animateWithDuration:.3
delay:.0f
options:(UIViewAnimationOptionRepeat|
UIViewAnimationOptionAutoreverse)
animations:^{
[UIView setAnimationRepeatCount:1.5f];
... animate here ...
} completion:^(BOOL finished) {
[UIView animateWithDuration:.3 animations:^{
... finish the animation here ....
}];
}];
No flashing, works nice.
没有闪烁,很好用。
回答by GorillaPatch
There is a repeatCount
property on CAMediaTiming
. I think you have to create an explicit CAAnimation
object, and configure it properly. The repeatCount for grow and ungrow would be 2, but you can test this.
上有一处repeatCount
房产CAMediaTiming
。我认为您必须创建一个显式CAAnimation
对象,并正确配置它。生长和生长的重复计数将为 2,但您可以对此进行测试。
Something a long the lines of this. You would need two CAAnimation objects though, one for the frame and one for the rotation.
这条线有点长。不过,您需要两个 CAAnimation 对象,一个用于框架,一个用于旋转。
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation"];
theAnimation.duration=3.0;
theAnimation.repeatCount=1;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:0.0];
theAnimation.toValue=[NSNumber numberWithFloat:degreesToRadians(34)];
[theLayer addAnimation:theAnimation forKey:@"animateRotation"];
AFAIK there is no way to avoid programming two animation objects.
AFAIK 没有办法避免对两个动画对象进行编程。