How to Pause and Resume Uiview.Animatewithduration

How to pause and resume UIView.animateWithDuration

2 functions to pause and resume animation, I take from here and convert to Swift.

func pauseLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
layer.speed = 0.0
layer.timeOffset = pausedTime
}

func resumeLayer(layer: CALayer) {
let pausedTime: CFTimeInterval = layer.timeOffset
layer.speed = 1.0
layer.timeOffset = 0.0
layer.beginTime = 0.0
let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
layer.beginTime = timeSincePause
}

I have a button to pause or resume the animation which is initiated in viewDidLoad:

var pause = false
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 10.5) {
self.image.transform = CGAffineTransformMakeTranslation(0.0, 200)
}
}

@IBAction func changeState() {
let layer = image.layer
pause = !pause
if pause {
pauseLayer(layer)
} else {
resumeLayer(layer)
}
}

Pause and resume AnimateWithDuration animations ios

Since your animation appears to be a sequence of several smaller sub-animations repeated ad infinitum, you could keep track of where you are in the animation loop at all times, stop the animation when your app becomes inactive, and restart the animation when your app becomes active again.

[Edit: sample code and explanations added below.]

In ViewController.m:

@interface ViewController ()
{
int numStages; // 4 * 3 = 12 in our example (4 different text labels,
// with 3 substages (alpha ramping up, alpha constant, and alpha ramping down) for each)
int globalStage; // varies from 0 to numStages - 1. 0 initially
bool animationIsActive;
}

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

numStages = 4 * 3; // 4 * 3 = 12 in our example (4 different text labels,
// with 3 substages for each text label's appearance (alpha ramping up, alpha constant, and alpha ramping down))
globalStage = 0; // varies from 0 to numStages - 1. 0 initially
animationIsActive = NO;

self.myLabel.alpha = 0.0;
}

- (void)animateStage:(int)stage {
NSLog(@"animateStage called with argument stage = %d", stage);

// make a note in our instance variable of where we need to restart
// the animation THE NEXT TIME if it is interrupted or paused
// during the current animation:
globalStage = (stage + 1) % numStages;

self.myLabel.text = [NSString stringWithFormat:@"Text %d", (stage / 3) + 1];

switch (stage % 3) {
case 0: // ramp up alpha from 0 to 1
{
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
case 1: // keep alpha constant at 1 (see comment below)
{
[UIView animateWithDuration:2.7 animations:^{
self.myLabel.alpha = 0.99999; // changing the 0.99999 to 1.0 causes
// this stage to be short-circuited. probably because iOS realizes
// that alpha is not really changing in this stage and, being too clever
// by half, decides to skip this stage altogether. but 0.99999 is
// as close to 1.0 as makes no difference.
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
case 2: // ramp down alpha from 1 to 0
{
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
default:
break;
}

}

- (void)viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear: called");
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(willResignActive:)
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
}

- (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"viewDidDisappear: called");
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
}

- (void)didBecomeActive:(NSNotification *)notification
{
NSLog(@"view controller's didBecomeActive: called");
// start the animation is we are stopped
if (!animationIsActive)
{
NSLog(@"animation being (re)started at stage %d", globalStage);
[self animateStage:globalStage];
animationIsActive = YES;
}
}

- (void)willResignActive:(NSNotification *)notification
{
NSLog(@"view controller's willResignActive: called");
// stop the animation
NSLog(@"animation being stopped at stage %d", globalStage);
animationIsActive = NO;
}

@end
  1. I've broken up and "flattened" your animation into 4 * 3 = 12 stages for finer control.
  2. The instance variables globalStage and animationIsActive are used to keep track of where we are in the animation and whether or not the animation is running.
  3. In viewWillAppear: we ask to be notified when the app becomes active or inactive. When these events occur, our methods didBecomeActive: or willResignActive: are called. These two methods are where we (re)start and stop our animations.
  4. Don't forget to unregister for the two UIApplication notifications in viewDidDisappear:.

UIView.animateWithDuration or UIScrollView.animateWithDuration - how to pause at current status

Try this custom UIScrollView class along with the UIViewController code.

class TouchScrollView : UIScrollView
{
var animatedScrollOffset = CGPointMake(0, 0)

func startAnimation()
{
UIScrollView.animateWithDuration(Double(5), delay: 1,
options: (UIViewAnimationOptions.AllowUserInteraction
| UIViewAnimationOptions.CurveLinear |
UIViewAnimationOptions.BeginFromCurrentState),
animations: {
self.contentOffset = self.animatedScrollOffset
},
completion: {
finished in
if !finished {

}
})

}

func stopAnimation()
{
let offset = self.layer.presentationLayer().bounds.origin
self.layer.removeAllAnimations()
self.contentOffset = offset
}

override init(frame: CGRect) {
super.init(frame: frame)

if let gestures = self.gestureRecognizers
{
for gestureRecognizer in gestures
{
if let swipeRecognizer = gestureRecognizer as? UIGestureRecognizer
{
swipeRecognizer.cancelsTouchesInView = false
}
}
}
}

required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.stopAnimation()
}

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
self.startAnimation()
}
}

class ViewController: UIViewController, UITextViewDelegate,UIScrollViewDelegate {

@IBOutlet var scrollView : TouchScrollView!

override func viewDidLoad() {

scrollView.contentSize = CGSizeMake(scrollView.frame.width, 10000)
scrollView.backgroundColor = UIColor.redColor()
scrollView.showsVerticalScrollIndicator = true
scrollView.showsHorizontalScrollIndicator = true
scrollView.animatedScrollOffset = CGPointMake(0, 1000)
scrollView.startAnimation()
scrollView.delegate = self
}

func scrollViewWillBeginDragging(_: UIScrollView) {
println("begin dragging")
scrollView.stopAnimation()
}

func scrollViewDidEndDragging(_ : UIScrollView, willDecelerate decelerate: Bool) {
println("end dragging")
if !decelerate
{
scrollView.startAnimation()
}
}

func scrollViewDidEndDecelerating(_ : UIScrollView) {
scrollView.startAnimation()
}

}

how to pause and resume an uiview animation when button clicking?

That is possible by using nstimer. Try using nstimer for starting and pausing animation here is a set of code which you can use. Implement your animation within a method and use the nstimer to fire it and pause it:

- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self startTimer];
}

- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self stopTimer];
}

- (void)startTimer {
NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:3.0] interval:3.0 target:self selector:@selector(this is where your animation method name goest) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
self.animationmethodename = timer;
[timer release];
}

- (void)stopTimer {
[self.animationmethodname invalidate];
self.animationmethodtimer = nil;
}

Then replace the animationmethodname with the name of the method you are using to create the animation.



Related Topics



Leave a reply



Submit