Pause and resume AnimateWithDuration animations ios

前端 未结 1 1430
孤独总比滥情好
孤独总比滥情好 2021-01-28 20:42

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

相关标签:
1条回答
  • 2021-01-28 21: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:.
    0 讨论(0)
提交回复
热议问题