iOS,退出后台时重新启动animation

当我的应用程序出来的背景animation已经停止。 这是正常的。 但我想从当前状态重新开始我的animation。 我如何做到这一点,而不是在我所有的地方。

[UIView animateWithDuration:60 delay:0 options:(UIViewAnimationOptionCurveLinear |UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) animations:^{ [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; } completion:nil]; 

我试图在animation前面放置一个框架,但是这只是让它抓拍。

 [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; 

有任何想法吗?

以及@ dany_23的答案可以工作。

但是我遇到了另一种方法,如果你不需要恢复你的animation,但重新启动你的animation,没有视图或图层捕捉,当你重新激活应用程序时,工作得很好。

在里面

 - (void)applicationWillResignActive:(UIApplication *)application 

你可以在你的viewcontroller中调用一个实现下面代码的方法。

 [view.layer removeAllAnimations]; // this following CGRect is the point where your view originally started [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; 

和在

 - (void)applicationDidBecomeActive:(UIApplication *)application 

你在视图控制器中调用一个刚开始animation的方法。 就像是

 [UIView animateWithDuration:60 delay:0 options:(UIViewAnimationOptionCurveLinear |UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) animations:^{ [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; } completion:nil]; 

希望这有助于,感谢所有谁回答。

你可以在你的类的UIApplicationWillEnterForegroundNotification中添加一个观察者:

 - (void)addNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; } - (void)applicationWillEnterForeground { [self animate]; } - (void)animate { [bg setFrame:CGRectMake(0, 0, 0, 0)]; [UIView animateWithDuration:60 delay:0 options:(UIViewAnimationOptionCurveLinear |UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) animations:^{ [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; } completion:nil]; } 

设置animation的开始状态很重要(不要忘记删除通知观察者)

当您的应用进入后台时,您必须暂停animation,并在其重新变为活动状态时重新开始。 您可以在这里find一些示例代码,介绍如何暂停和恢复animation。

那么如果我正确地理解了这个问题,那么你就试图创build一个animation,并把它停在中间。

在这种情况下,我build议你使用某种“状态”variables来存储animation的状态(例如框架属性)。 这个variables,你可以在进一步的代码中使用,把被animation的对象放在正确的位置。 这可以在animationDidStop函数( animationDidStop:finished:)中完成 。 为了实现这个function,你将不得不使用委托。 它意味着将AppNameViewController(或整个应用程序的其他独特对象)设置为animation的委托,并将实现写入其m文件中。 这将允许您在animation结束时运行“位置设置”代码。

接下来的任务是存储animation状态。 在运行animation时,Core Animation框架创build了一堆中间层(表示层)。 这些图层在animation中显示,然后被删除。 当animation完成执行时,对象只是被置于最终状态。 实际上,当你创build所谓的“显式animation”时,你必须设置它(如果你不这样做,animation将会播放,但是对象将会跳回到最后)。 每个表示层都有一组或所有属性的副本,称为“animation属性”。 当其中一个animation属性设置为animation的关键字时,Core Animation调用(BOOL)needsDisplayForKey返回YES / NO。 它告诉Core Animation对指定键的更改是否需要重新显示图层。 “重新显示”意味着为表示层调用drawInContext方法。 在这里,您可以获取当前显示的表示层的属性,并将其置于“状态”variables中。

在线程中播放animation,并设置我使用委托的“状态”variables。 它需要inheritanceCALayer(让我们说AnimLayer),并用一个存储“状态”的方法定义一个协议。 这个方法有一个参数就是状态。 然后,我实现了将状态存储在AnimLayer类中的协议方法,并将唯一对象设置为委托。 所以这些表示层(AnimLayer副本)不会自己存储状态。 相反,作为parameter passing给委托函数的“状态”值由主线程中的唯一对象存储。

我做了这样的事情,但我的任务有点不同。 我不知道更简单的方法,对不起。 希望这可以帮助。

这样做会更好,只需注册ApplicationDelegate就会成为方法和观察者的状态。

 - (void)pauseAnimate{ CFTimeInterval pausedTime = [self.layer timeOffset]; self.layer.speed = 1.0; self.layer.timeOffset = 0.0; self.layer.beginTime = 0.0; CFTimeInterval timeSincePause = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; self.layer.beginTime = timeSincePause; } - (void)stopAnimate{ CFTimeInterval pausedTime = [self.layer convertTime:CACurrentMediaTime() fromLayer:nil]; self.layer.speed = 0.0; self.layer.timeOffset = pausedTime; } 

这里比每次从后台重新开始整个animation都有更好的解决方法。

对于Swift 3,你可以inheritance这个类:

 class ViewWithPersistentAnimations : UIView { private var persistentAnimations: [String: CAAnimation] = [:] private var persistentSpeed: Float = 0.0 override init(frame: CGRect) { super.init(frame: frame) self.commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.commonInit() } func commonInit() { NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } func didBecomeActive() { self.restoreAnimations(withKeys: Array(self.persistentAnimations.keys)) self.persistentAnimations.removeAll() if self.persistentSpeed == 1.0 { //if layer was plaiyng before backgorund, resume it self.layer.resume() } } func willResignActive() { self.persistentSpeed = self.layer.speed self.layer.speed = 1.0 //in case layer was paused from outside, set speed to 1.0 to get all animations self.persistAnimations(withKeys: self.layer.animationKeys()) self.layer.speed = self.persistentSpeed //restore original speed self.layer.pause() } func persistAnimations(withKeys: [String]?) { withKeys?.forEach({ (key) in if let animation = self.layer.animation(forKey: key) { self.persistentAnimations[key] = animation } }) } func restoreAnimations(withKeys: [String]?) { withKeys?.forEach { key in if let persistentAnimation = self.persistentAnimations[key] { self.layer.add(persistentAnimation, forKey: key) } } } } extension CALayer { func pause() { if self.isPaused() == false { let pausedTime: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil) self.speed = 0.0 self.timeOffset = pausedTime } } func isPaused() -> Bool { return self.speed == 0.0 } func resume() { let pausedTime: CFTimeInterval = self.timeOffset self.speed = 1.0 self.timeOffset = 0.0 self.beginTime = 0.0 let timeSincePause: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil) - pausedTime self.beginTime = timeSincePause } } 

它将负责暂停当前状态下的所有animation,并在应用程序来自后台时重新添加animation,而不用重置它们。

要点: https : //gist.github.com/grzegorzkrukowski/a5ed8b38bec548f9620bb95665c06128

我不记得确切的细节,但我想你可以通过查看你的视图的图层边界和位置属性来获得框架的当前animation位置。 您可以将这些应用程序保存在应用程序中,并在应用程序再次处于前台时进行还原。