How can I pause a currently running animation? - iphone

I have a Core Animation running and want to pause it when a button is pressed. So there is a method -pauseAnimation. When the animation is paused, I want the animated view to stay in the state as it currently was while animating. i.e. if a view moves from top left to bottom right, and somewhere in the middle the animation is paused, the view should stay in the middle.
Is there a way to do this?
as far as i can remember there is an setAnimationsEnabled=NO option, but that doesn't work when the animation runs, right?

You can pause layer animations by setting the speed of the animation to zero, see How to pause the animation of a layer tree.

You can do this by disabling animations and then setting the model layers' values to the presentation layers' values (for all properties that define your animation).
eg. layer.transform = layer.presentationLayer.transform;
Resuming the animation = re-enable animations and animate from current positions to the desired final positions (you might have to adjust curves, etc to get something acceptable).

Related

Pausing and restarting animations

I'm working on a test that uses swift UIKit dynamics to animate a ball across the screen. I want to add a button in the top left of the screen, that when pressed, pauses the screen just how it is, then when pressed again, resumes the animation. If anyone has any suggestions on how to go about doing this that would be much appreciated. Thank you
The simplest thing to do is to set the speed of the layer of a superview that contains all views being animated to 0:
self.view.layer.speed = 0
Then set it back to 1.0 when you want the animation to continue.
(It isn't obvious that layers have a speed property. It is there because they conform to the CAMediaTiming protocol.)

UIView 3D transform final frame location

I have a UIView which has an X origin that makes it off screen to the right. Then, I do a keyframe animation with CATransform3D:
[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-view.width, 0, 0)]
The problem is, after the animation completes, the view's frame is visually in the correct place, but it still thinks it's off screen, so I can't interact with it. Logging its frame property also shows that it's offscreen, but visually, it's not.
The fill mode for the animation is kCAFillModeForwards, so the final value of the animation sticks.
What is the solution to this problem, that is, interacting with this view after the animation and notifying the view that it is indeed visible?
You can use CAAnimation delegate method -animationDidStop:finished: to fix it when the animation done:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
...
}
The better answer is to use UIView animation methods like animateWithDuration:animations:completion: (and variants on that method.)
Those methods let you do animations on the actual view properties, and when the animation is complete, the view is at it's actual destination location.
The center property is the easiest way to move views around. The frame property isn't valid if you've applied a transform, but the center property IS always valid for both reading and writing.
Core Animation only creates the illusion that your views move. The animation takes place on a display-only copy of the layer tree. You can query the properties of an animating layer by reading those same properties from the layer's presentationLayer. However, the view objects will not respond to the user interaction at their apparent location. The views still think they are at their original locations.
As the other poster said, you could use the animation completion delegate method to move the view to it's final location once the animation is over, but that's a lot of fussy work to do something that UIView animation does for you much more cleanly and simply.
Can you interact with the view even before you animate it?
is the view.userInteractionEnabled is set to YES??

How can I callback as a CABasicAnimation is animating?

I have an animation I'm using to snap a rotatable UIView to a circular grid. As the view animates, I need to update another view based on the rotating views position.
How can I go about getting the position of the rotating view as it animates into position?
When animation starts you can start a function that will be polling current view position using a timer (I suppose you will need to get presentationLayer from view's layer and get position values from it).
There's no callbacks for CAAnimation other than animationDidStart and animationDidStop so it seems that's the solution (if I'm not mistaken it was also mentioned so in one of WWDC videos).

Is there an way to pause an Core Animation and resume it at some time later?

I have several Core Animation's going on at the same time. They all have an context and an animation id, where the context is the object that's beeing animated (UIImageView objects). I would like to pause them, so that the animation just stops temporarily, and then when some things are done, resume it to complete it. These things happen only on very fast scroll movements in an UIScrollView. I want to improve performance by stopping all ongoing animations but not the one that makes the scroll view scroll. I have implemented an custom animation of the contentOffset for that scroll view.
You can pause layer animations by setting the speed of the animation to zero, see How to pause the animation of a layer tree.
To anyone who comes searching, this is how you pause and resume animations:
https://developer.apple.com/library/archive/qa/qa1673/_index.html
The only way I have gotten around this is the following.
For each view you wish to stop animating:
Set the view's frame to the presentation layer
Remove all animations from that view
Perform your scroll
Recalculate animations
Add new animations to the view
I know it isn't what you want to hear, but it isn't as bad as it sounds. A good way to track the views you want to stop is to give them a predetermined tag.
To remove animations:
[myView.layer removeAllAnimations]
[myView.layer removeAnimationForKey:#"theAnimationKey"]
The Core Animation Programming Guide has a section on Customizing the Timing of an Animation which includes a section on Pausing and Resuming Animations.

Is there a way to swap layers or views in the middle of a CAKeyframeAnimation?

I am running a keyFrame animation to move and flip a playing card view using CAKeyframeAnimation. is there any way to swap the cardFront and cardBack layers during the animation? or am i taking the wrong approach here...
use a timer set to half the animation duration to execute cardBack.contents = cardFront.contents