Pause and resume AnimateWithDuration animations io

2019-03-05 12:21发布

So I have done animations based with the help of method animateWithDuration but i need to stop animation when app goes in background and resume when app comes back in foreground.

Is there a way i can achieve this:-

My animations : label fade in fade out after certain intervals;

- (void)viewDidLoad {
    [super viewDidLoad];

    [self MyLabelAnimation];

}

- (void)MyLabelAnimation {
    self.myLabel.text = @"Text 1";
    [UIView animateWithDuration:0.3 animations:^{
        self.myLabel.alpha = 1.0;
    } completion:^(BOOL finished) {

        [UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.myLabel.alpha = 0.0;
        } completion:^(BOOL finished) {

            self.myLabel.text = @"Text 2";
            [UIView animateWithDuration:0.3 animations:^{
                self.myLabel.alpha = 1.0;
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                    self.myLabel.alpha = 0.0;
                } completion:^(BOOL finished) {

                    self.myLabel.text = @"Text 3";
                    [UIView animateWithDuration:0.3 animations:^{
                        self.myLabel.alpha = 1.0;
                    } completion:^(BOOL finished) {

                        [UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                            self.myLabel.alpha = 0.0;
                        } completion:^(BOOL finished) {

                            self.myLabel.text = @"Text 4";
                            [UIView animateWithDuration:0.3 animations:^{
                                self.myLabel.alpha = 1.0;
                            } completion:^(BOOL finished) {
                                [UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                                    self.myLabel.alpha = 0.0;
                                } completion:^(BOOL finished) {

                                    [self MyLabelAnimation];
                                }];
                            }];
                        }];
                    }];
                }];
            }];
        }];
    }];
}

1条回答
祖国的老花朵
2楼-- · 2019-03-05 13:10

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:.
查看更多
登录 后发表回答