2017-08-14 78 views
0

我有一個imageView,並希望它始終旋轉360°,但我發現的問題是,當應用程序進入background,然後回到​​,旋轉動畫將停止。 而我不想在應用程序回到前臺時重新調用函數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) 

    } 

回答

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的360度旋轉而旋轉,然後通過180度視圖。 .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

+0

@Hi beyowulf。感謝您的詳細回覆。我會嘗試解決您的問題。但問題是持續時間不適用於後臺或前臺應用程序。它只涉及用戶的行爲。例如,該應用程序是音樂播放器,imageView用於音樂作品,用戶可以用後臺模式聽音樂30分鐘,2小時或更長時間。 – Ringo

+0

我不明白你的意見。應用程序在後臺的持續時間可以是任何無關緊要,只要應用程序停留在內存中即可。我認爲問題是如何爲視圖設置動畫,以便在應用程序背景時恢復動畫,繼續播放,就好像它從未背景一樣。情況並非如此嗎? – beyowulf

+0

哦,對不起,我誤解了你的代碼中的數字10。這是動畫的持續時間,而不是應用程序在後臺的時間。 – Ringo

相關問題