如何在应用程序返回前台时恢复核心动画

时间:2017-08-14 16:41:51

标签: ios swift uiimageview core-animation cadisplaylink

我有一个imageView并希望它一直旋转360°,但我发现一个问题是,当应用程序进入background然后再回到foreground时,旋转动画将会停下来 当应用程序回到前台时,我不想重新调用函数rotate360Degree(),原因是我希望旋转动画将在进入背景时从它离开的位置开始,而不是旋转再次从0开始。 但是当我调用函数resumeRotate()时,它不起作用。

扩展名如下:

extension UIImageView {
    // 360度旋转图片
    func rotate360Degree() {
        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z") // 让其在z轴旋转
        rotationAnimation.toValue = NSNumber(value: .pi * 2.0) // 旋转角度
        rotationAnimation.duration = 20 // 旋转周期
        rotationAnimation.isCumulative = true // 旋转累加角度
        rotationAnimation.repeatCount = MAXFLOAT // 旋转次数
        rotationAnimation.autoreverses = false
        layer.add(rotationAnimation, forKey: "rotationAnimation")
    }

    // 暂停旋转
    func pauseRotate() {

        layer.pauseAnimation()
    }

    // 恢复旋转
    func resumeRotate() {

        layer.resumeAnimation()


    }

}

这是图层扩展名:

var pauseTime:CFTimeInterval!

extension CALayer {
    //暂停动画
    func pauseAnimation() {
        pauseTime = convertTime(CACurrentMediaTime(), from: nil)
        speed = 0.0
        timeOffset = pauseTime
    }
    //恢复动画
    func resumeAnimation() {
        // 1.取出时间
         pauseTime = timeOffset
        // 2.设置动画的属性
        speed = 1.0
        timeOffset = 0.0
        beginTime = 0.0
        // 3.设置开始动画
        let startTime = convertTime(CACurrentMediaTime(), from: nil) - pauseTime
        beginTime = startTime
    }
}

我可以用CADisplayLink解决上面的“已停止”问题,但动画不会从它离开的位置旋转(一直旋转)。  我想知道如何使用CADisplayLink解决它? 以及如何使用上述核心动画?

displayLink = CADisplayLink(target: self, selector: #selector(rotateImage))
displayLink.add(to: .current, forMode: .commonModes)

 func rotateImage(){

         let angle =  CGFloat(displayLink.duration * Double.pi / 18)

         artworkImageView.transform = artworkImageView.transform.rotated(by: angle)

    }

1 个答案:

答案 0 :(得分:0)

您可以使用UIKit基于更高级别块的动画api执行此操作。如果您想要持续旋转视图,持续时间为20.0秒。您可以使用以下功能:

    func animateImageView()
    {
        UIView.animate(withDuration: 10.0, delay: 0.0, options: [.beginFromCurrentState, .repeat, .curveLinear], animations:
        { [unowned self] in
            var transform = self.imageView.transform
            transform = transform.concatenating(CGAffineTransform(rotationAngle: CGFloat.pi))
            self.imageView.transform = transform
        },
        completion:
        { _ in
            UIView.animate(withDuration: 10.0, delay: 0.0, options: [.beginFromCurrentState, .curveLinear], animations:
            { [unowned self] in
                var transform = self.imageView.transform
                transform = transform.concatenating(CGAffineTransform(rotationAngle: CGFloat.pi / 2.0))
                self.imageView.transform = transform
            })
        })
    }

这只是将视图旋转180度然后一旦完成旋转另一个180度旋转360度。 .repeat选项将使其无限重复。但是,当应用程序背景时,动画将停止。为此,我们需要保存正在旋转的视图的表示层的状态。我们可以通过存储表示层的CGAffineTransform然后将该变换设置为当应用程序返回到前台时动画的视图来实现。以下是UIImageView

的示例
class ViewController: UIViewController
{

    @IBOutlet weak var imageView: UIImageView!
    var imageViewTransform = CGAffineTransform.identity

    override func viewDidLoad()
    {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(self.didEnterBackground), name: .UIApplicationDidEnterBackground, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.willEnterForeground), name: .UIApplicationWillEnterForeground, object: nil)
    }

    override func viewDidAppear(_ animated: Bool)
    {
        super.viewDidAppear(animated)
        animateImageView()
    }

    deinit
    {
        NotificationCenter.default.removeObserver(self)
    }

    func didEnterBackground()
    {
        imageViewTransform = imageView.layer.presentation()?.affineTransform() ?? .identity
    }

    func willEnterForeground()
    {
        imageView.transform = imageViewTransform
        animateImageView()
    }

    func animateImageView()
    {
        UIView.animate(withDuration: 10.0, delay: 0.0, options: [.beginFromCurrentState, .repeat, .curveLinear], animations:
        { [unowned self] in
            var transform = self.imageView.transform
            transform = transform.concatenating(CGAffineTransform(rotationAngle: CGFloat.pi))
            self.imageView.transform = transform
        },
        completion:
        { _ in
            UIView.animate(withDuration: 10.0, delay: 0.0, options: [.beginFromCurrentState, .curveLinear], animations:
            { [unowned self] in
                var transform = self.imageView.transform
                transform = transform.concatenating(CGAffineTransform(rotationAngle: CGFloat.pi / 2.0))
                self.imageView.transform = transform
            })
        })
    }
}

结果如下:

enter image description here