暂停和恢复 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 个阶段,以便更好地控制。
实例变量
globalStage
和animationIsActive
用于跟踪我们在动画中的位置以及动画是否正在运行。
在viewWillAppear:
中,我们要求在应用程序变为活动或不活动时收到通知。当这些事件发生时,我们的方法didBecomeActive:
或willResignActive:
被调用。这两种方法是我们(重新)开始和停止动画的地方。
不要忘记取消注册viewDidDisappear:
中的两个UIApplication
通知。
【讨论】:
我该怎么做..我不知道如何阻止它? 我在原始答案中添加了一些示例代码和详细说明。享受吧! 我想问你一件事.. 假设我在动画之间时假设我延迟了 2.7 秒,如果用户在不到 2.7 秒内进入后台和前台。然后这个动画没有关闭,而是生成了一个新的动画,它打破了流程...... 你说的很对;动画在下一阶段重新开始。如果您需要更细粒度的控制,您可以将 2.7 秒的延迟分解为 9 次连续延迟,每次延迟 0.3 秒。所以现在你将拥有numStages = 4 * 11
、stage / 11
而不是stage / 3
、stage % 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 - 如何在当前状态暂停