2017-08-14 2 views
0

J'ai un imageView et je veux qu'il tourne à 360 ° tout le temps, mais j'ai trouvé un problème qui est que lorsque l'App entre background, puis de nouveau au foreground, le tourner l'animation sera arrêté. Et je ne veux pas rappeler la fonction rotate360Degree() lorsque l'application revient au premier plan, la raison en est que je veux que l'animation de rotation commence à la position où il est parti en entrant en arrière-plan, au lieu de tourner à nouveau 0 . Mais quand j'appelle la fonction resumeRotate(), cela ne fonctionne pas.Comment faire pour reprendre l'animation de base lorsque l'application revient au premier plan

L'extension comme suit:

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() 


    } 

} 

Voici la couche d'extension:

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 
    } 
} 

je peux résoudre le problème ci-dessus STOPPED avec CADisplayLink, mais l'animation ne tourne pas de la position où il est parti (tourner tout le temps). Je me demande comment le résoudre avec CADisplayLink? Et comment avec l'animation de base ci-dessus?

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) 

    } 

Répondre

0

Vous pouvez le faire avec UIKit « s bloc de niveau supérieur api d'animation basé. Si vous voulez une vue en rotation continue avec une durée de 20 secondes. Vous pouvez avec une fonction comme:

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 
      }) 
     }) 
    } 

Cela vient faire pivoter la vue de 180 degrés puis une fois que terminée le faire pivoter une autre 180 pour une rotation à 360 degrés. L'option .repeat entraîne la répétition indéfinie. Cependant, l'animation s'arrêtera lorsque l'application sera en arrière-plan. Pour cela, nous devons sauvegarder l'état de la couche de présentation de la vue en cours de rotation. Nous pouvons le faire en stockant le CGAffineTransform du calque de présentation, puis en définissant cette transformation sur la vue animée lorsque l'application revient au premier plan. Voici un exemple avec un 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 
      }) 
     }) 
    } 
} 

qui se traduit par ceci:

enter image description here

+0

@Hi beyowulf. Merci pour votre réponse en détail. Je vais essayer avec votre solution.Mais la question est que la durée n'est pas fixée pour l'application en arrière-plan ou au premier plan.Il s'agit juste du comportement de l'utilisateur.Par exemple, l'application est une musique joueur, l'imageView est pour l'illustration de la musique, et l'utilisateur peut écouter la musique avec le mode d'arrière-plan pendant 30 minutes, 2 heures ou plus. – Ringo

+0

Je ne comprends pas votre commentaire. La durée pendant laquelle l'application est en arrière-plan peut être ce qu'elle n'a pas d'importance, à condition que l'application reste en mémoire. Je pensais que la question était de savoir comment animer une vue de sorte que lorsque l'application est en arrière-plan, puis repris l'animation continue comme si elle n'avait jamais été arrière-plan. N'est-ce pas le cas? – beyowulf

+0

Oh, désolé, j'ai mal compris le chiffre 10 dans vos codes. C'est la durée de l'animation au lieu de l'heure de l'application en arrière-plan. – Ringo