具有自动反转功能的 UIView 动画
我的 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 ];
问题是,动画反转后,视图跳回到动画块中设置的帧。我希望视图能够增长和“不增长”并停止在其原始位置。
有没有不用编程两个连续动画的解决方案?
I have a problem with the setting UIViewAnimationOptionAutoReverse
.
Here is my code.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你有三个选择。
当您使用
-[UIView animateWithDuration:…]
方法时,您在animations
块中所做的更改将立即应用于相关视图。然而,还有一个隐式的CAAnimation
应用于从旧值到新值的动画视图。当 CAAnimation 在视图上处于活动状态时,它会更改显示的视图,但不会更改视图的实际属性。例如,如果您这样做:
您将看到“旧中心”和“新中心”是不同的;新中心将立即反映newPoint 的值。然而,隐式创建的
CAAnimation
将导致视图仍然显示在旧中心,并平滑地移动到新中心。动画完成后,它将从视图中删除,您将切换回仅查看实际模型值。当您传递
UIViewAnimationOptionAutoreverse
时,它会影响隐式创建的CAAnimation
,但不会影响您对值所做的实际更改。也就是说,如果我们上面的示例定义了UIViewAnimationOptionAutoreverse
,那么隐式创建的CAAnimation
将从 oldCenter 到 newCenter 并返回。然后动画将被删除,我们将切换回查看我们设置的值......仍处于新位置。正如我所说,有三种方法可以解决这个问题。第一个是在动画上添加一个完成块来反转它,如下所示:
第一个选项
第二个选项
第二个选项是像您正在做的那样自动反转动画,并将视图设置回其在完成块中的原始位置:
但是,这可能会导致动画自动反转完成和完成块运行之间出现闪烁,因此它可能不是您的最佳选择。
第三个选项
最后一个选项是直接创建一个
CAAnimation
。当您实际上不想更改要更改的属性的最终值时,这通常更简单。请注意,
CAAnimation
的处理方式永远不会更改视图的实际值;它只是用动画掩盖实际值。该视图仍然认为它位于原始位置。 (这意味着,例如,如果您的视图响应触摸事件,它仍然会监视这些触摸事件在原始位置发生。动画仅改变视图的绘制方式;没有任何改变否则,CAAnimation
方式还要求您将其添加到视图的底层CALayer
中,如果这让您感到害怕,请随意使用-[UIView animateWithDuration:... ]
方法可以通过使用 CAAnimation 来实现,但如果您不熟悉的话,链接 UIView 动画或在完成块中重置它实际上是完全可以接受的。 ,这是完成块的主要目的之一,因此,您可以使用三种不同的方式来反转动画并保持原始值。
You have three options.
When you use the
-[UIView animateWithDuration:…]
methods, the changes you make in theanimations
block are applied immediately to the views in question. However, there is also an implicitCAAnimation
applied to the view that animates from the old value to the new value. When aCAAnimation
is active on a view, it changes the displayed view, but does not change the actual properties of the view.For example, if you do this:
you will see that 'old center' and 'new center' are different; new center will immediately reflect the values of newPoint. However, the
CAAnimation
that was implicitly created will cause the view to still be displayed at 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.When you pass
UIViewAnimationOptionAutoreverse
, it affects the implicitly createdCAAnimation
, but does NOT affect the actual change you're making to the values. That is, if our example above had theUIViewAnimationOptionAutoreverse
defined, then the implicitly createdCAAnimation
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.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
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:
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.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 only changes the way the view draws; nothing else.The
CAAnimation
way also requires that you add it to the view's underlyingCALayer
. If this scares you, feel free to use the-[UIView animateWithDuration:…]
methods instead. There's additional functionality available by usingCAAnimation
, 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.So, there you go. Three different ways to reverse an animation and keep the original value. Enjoy!
这是我的解决方案。对于 2x 重复,动画 1.5x 并自己完成最后 0.5x 部分:
无闪烁,效果很好。
Here's my solution. For 2x repeat, animate 1.5x and do the last 0.5x part by yourself:
No flashing, works nice.
CAMediaTiming 上有一个
repeatCount
属性。我认为您必须创建一个显式的 CAAnimation 对象,并正确配置它。增长和取消增长的重复计数将为 2,但您可以对此进行测试。这句话的内容很长。不过,您需要两个 CAAnimation 对象,一个用于框架,一个用于旋转。
AFAIK 没有办法避免对两个动画对象进行编程。
There is a
repeatCount
property onCAMediaTiming
. I think you have to create an explicitCAAnimation
object, and configure it properly. The repeatCount for grow and ungrow would be 2, but you can test this.Something a long the lines of this. You would need two CAAnimation objects though, one for the frame and one for the rotation.
AFAIK there is no way to avoid programming two animation objects.
这是 @Rudolf Adamkovič 答案的 Swift 版本,您可以将动画设置为运行 1.5 次,并在完成块中最后一次运行“反向”动画。
在下面的代码片段中,我将我的视图在 y 轴上平移 -10.0 点 1.5 倍。然后在完成块中,我最后一次将视图动画化回其原始 y 轴位置 0.0。
Here is a Swift version of @Rudolf Adamkovič's answer, where you set the animation to run 1.5 times and in the completion block run a 'reverse' animation one final time.
In the below snippet I am translating my view by -10.0 pts on the y-axis 1.5 times. Then in the completion block I animate my view one final time back to its original y-axis position of 0.0.