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

Stu*_*tus 21 iphone core-animation objective-c ipad ios

当我的应用程序退出后台时动画停止了.这是正常的.但我想从当前状态重新启动我的动画.如果没有我到处偷拍,我怎么做到这一点.

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

我尝试在动画前放置一个设置框架,但这只是让它快速捕捉.

[bg setFrame:CGRectMake(0, 0, 1378, 1005)];
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Jon*_*han 27

好吧,@ dany_23的答案可行.

但是我遇到了另一种方法,如果您不需要恢复动画但重新启动动画,而不重新激活应用程序时视图或图层对齐,则该方法可以正常工作.

在里面

- (void)applicationWillResignActive:(UIApplication *)application
Run Code Online (Sandbox Code Playgroud)

您在viewcontroller中调用一个实现以下代码的方法.

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

并在

- (void)applicationDidBecomeActive:(UIApplication *)application
Run Code Online (Sandbox Code Playgroud)

你在viewcontroller中调用一个只启动动画的方法.就像是

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

希望这会有所帮助,感谢所有回复的人.


Ram*_*iro 27

您可以在类中为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];
}
Run Code Online (Sandbox Code Playgroud)

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

  • _ + 1_通知是比使用应用程序委托更好的方式来接收此类事件. (3认同)
  • +1这绝对是重新启动循环动画的更灵活,更优雅的解决方案。UIApplicationDelegate不必关心重新启动MYWaitCycleView的旋转鸡动画。@Ramiro的代码非常适合坐在UIViewController或UIView子类中,非常接近要动画的对象。 (2认同)

Grz*_*ski 8

与每次您从背景开始重新启动整个动画相比,这里有一个更好的解决方法。

对于Swift 3,您可以继承此类:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

它将暂停所有处于当前状态的动画,并在应用来自后台时重新添加动画-无需重置它们。

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


Ste*_*ghe 5

当应用程序进入后台时,您必须暂停动画,并在应用程序再次激活时恢复动画。您可以在此处找到一些示例代码,描述如何暂停和恢复动画。