暂停和恢复 AnimateWithDuration 动画 ios

Posted

技术标签:

【中文标题】暂停和恢复 AnimateWithDuration 动画 ios【英文标题】:Pause and resume AnimateWithDuration animations ios 【发布时间】:2016-10-03 18:50:39 【问题描述】:

所以我在方法 animateWithDuration 的帮助下完成了动画,但是我需要在应用程序进入后台时停止动画,并在应用程序返回前台时恢复。

有什么办法可以做到这一点:-

我的动画:标签在一定间隔后淡入淡出;

- (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】:

由于您的动画似乎是由多个较小的子动画无限重复的序列,因此您可以随时跟踪您在动画循环中的位置,在您的应用处于非活动状态时停止动画,然后重新启动动画当您的应用再次激活时。

[编辑:下面添加了示例代码和说明。]

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
    我已将您的动画分解并“扁平化”为 4 * 3 = 12 个阶段,以便更好地控制。 实例变量globalStageanimationIsActive 用于跟踪我们在动画中的位置以及动画是否正在运行。 在viewWillAppear: 中,我们要求在应用程序变为活动或不活动时收到通知。当这些事件发生时,我们的方法didBecomeActive:willResignActive: 被调用。这两种方法是我们(重新)开始和停止动画的地方。 不要忘记取消注册viewDidDisappear: 中的两个UIApplication 通知。

【讨论】:

我该怎么做..我不知道如何阻止它? 我在原始答案中添加了一些示例代码和详细说明。享受吧! 我想问你一件事.. 假设我在动画之间时假设我延迟了 2.7 秒,如果用户在不到 2.7 秒内进入后台和前台。然后这个动画没有关闭,而是生成了一个新的动画,它打破了流程...... 你说的很对;动画在下一阶段重新开始。如果您需要更细粒度的控制,您可以将 2.7 秒的延迟分解为 9 次连续延迟,每次延迟 0.3 秒。所以现在你将拥有numStages = 4 * 11stage / 11 而不是stage / 3stage % 11 而不是stage % 3,等等。case 2: 的代码现在将成为case 10: 的代码。摆脱现有的default: 并将case 1: 设为新的default:(新的默认值将覆盖case 1:case 9:)。此外,将其alpha 设置从0.99999 更改为(1.0 - 0.00001 * (stage % 11))

以上是关于暂停和恢复 AnimateWithDuration 动画 ios的主要内容,如果未能解决你的问题,请参考以下文章

UIView.animateWithDuration 或 UIScrollView.animateWithDuration - 如何在当前状态暂停

如何暂停和恢复 UIDynamicAnimator 物理模拟

在 iphone 中暂停和恢复 CLLocation 跟踪

摇摆动画暂停和恢复

Redshift 暂停和恢复

SpriteKit 暂停和恢复 SKView