Thomas Joos
Thomas Joos

Reputation: 2451

How to pause and resume UIView Animation?

I have a UIView with several UILabels that is animating from top to bottom and vice versa. A sort of Autoque let's say :) I use 2 functions:

-(void)goUp 
-(void)goDown 

Those functions start a UIView animation to the required position.They both have an AnimationDidStopSelector defined that calls the other function at the end. This all works smoothly.

When touching the screen, using touchesBegan, I would like to pause the current animation and change the vertical position of the UIView using touchesMoved event. In touchesEnded I want to resume the animation to the required end position.

What would be the proper way to do so?

Thomas

Upvotes: 4

Views: 12221

Answers (5)

DonnaLea
DonnaLea

Reputation: 8653

Actually, you can still pause the UIView animations based on the answer to the question that Vladimir linked to as it pause my CABasicAnimations as well as my UIView animations after I had implemented all my animations as CABasicaAnimations and then added some UIView animations afterwards that I had thought wouldn't be paused, but they didn't work either. This is the relevant link.

I wanted to pause my whole view so I passed self.view.layer as the layer to be paused. But for those who don't know about CALayer's, pass in the view.layer that you want paused. Each UIView has a CALayer, so just pass in the upmost view.layer that is relevant for you. In the case of Thomas, based on your own answer, it would seem that you would want to pass in self.containerView.layer to be paused.

The reason that this works is because UIView animations are simply a layer on top of Core Animation. At least that's my understanding.

Hope this helps future people wondering how to pause animations.

Upvotes: 4

Antoine
Antoine

Reputation: 23976

I've created a category on UIView to pause and stop animations:

@interface UIView (AnimationsHandler)

- (void)pauseAnimations;
- (void)resumeAnimations;

@end

@implementation UIView (AnimationsHandler)
- (void)pauseAnimations
{
    CFTimeInterval paused_time = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    self.layer.speed = 0.0;
    self.layer.timeOffset = paused_time;
}

- (void)resumeAnimations
{
    CFTimeInterval paused_time = [self.layer timeOffset];
    self.layer.speed = 1.0f;
    self.layer.timeOffset = 0.0f;
    self.layer.beginTime = 0.0f;
    CFTimeInterval time_since_pause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - paused_time;
    self.layer.beginTime = time_since_pause;
}

Upvotes: 7

rbbtsn0w
rbbtsn0w

Reputation: 75

Hope it will help you.

- (void)goUP{
    CFTimeInterval pausedTime = [self.layer timeOffset];
    self.layer.speed = 1.0;
    self.layer.timeOffset = 0.0;
    self.layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    self.layer.beginTime = timeSincePause;
}

- (void)goDown{
    CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil];
    self.layer.speed = 0.0;
    self.layer.timeOffset = pausedTime;
}

When you call the Layer animate, it will effect all layer tree and submode layer animate.

Upvotes: 0

Thomas Joos
Thomas Joos

Reputation: 2451

Vladimir, the question about CAAnimations make sense.. but I found a way to 'pause' so I could keep using UIView animations:

CALayer *pLayer = [self.containerView.layer presentationLayer];
CGRect frameStop = pLayer.frame;
pausedX = frameStop.origin.x;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.01];
[UIView setAnimationCurve: UIViewAnimationCurveLinear];     
// set view properties

frameStop.origin.x = pausedX;
self.containerView.frame = frameStop;
[UIView commitAnimations];

What I'm doing here is using the presentationLayer to find out current x value of the animated view. After that I execute a new animation which overwrites the original animation. Make sure to setAnimationBeginsFromCurrentstate:YES for this. This cancels the original animation and puts the animated view not to it's destination position (which it does automatically ) but at the current position of the animation proces..

Hope this helps others too! :)

Upvotes: 2

Vladimir
Vladimir

Reputation: 170829

I'm not sure if it is possible with UIView's directly but you definitely can do that animating view's CALayers instead. See this question about pausing and resuming of CAAnimations.

Upvotes: 1

Related Questions