Juan Boero
Juan Boero

Reputation: 6427

Rotate UIView infinitely and pause/stop animation, keep state, and continue rotating from current state

I am having a hard time trying to pause and continue from the current state of the rotation any UIView rotation technique.

Tried:

CGAffineTransformRotate
CGAffineTransformMakeRotation
CATransform3DMakeRotation
CABasicAnimation

Basically, if i call view.layer.removeAllAnimations() or, layer.speed = 0 , they all reset current rotation degree.

Also tried snapshotting the view for using the image instead the true rotation, but with no luck, since the snapshot ignored rotation.

Upvotes: 1

Views: 1058

Answers (1)

Juan Boero
Juan Boero

Reputation: 6427

Finally got it, with more than one answer on SO, many in objective-c, put them all together in an UIView extension, and even documented:

extension UIView {

        /**
         Will rotate `self` for ever.

         - Parameter duration: The duration in seconds of a complete rotation (360º).
         - Parameter clockwise: If false, will rotate counter-clockwise.
         */
        func startRotating(duration duration: Double, clockwise: Bool) {
            let kAnimationKey = "rotation"
            var currentState = CGFloat(0)

            // Get current state
            if let presentationLayer = layer.presentationLayer(), zValue = presentationLayer.valueForKeyPath("transform.rotation.z"){
                currentState = CGFloat(zValue.floatValue)
            }

            if self.layer.animationForKey(kAnimationKey) == nil {
                let animate = CABasicAnimation(keyPath: "transform.rotation")
                animate.duration = duration
                animate.repeatCount = Float.infinity
                animate.fromValue = currentState //Should the value be nil, will start from 0 a.k.a. "the beginning".
                animate.byValue = clockwise ? Float(M_PI * 2.0) : -Float(M_PI * 2.0)
                self.layer.addAnimation(animate, forKey: kAnimationKey)
            }
        }

        /// Will stop a `startRotating(duration: _, clockwise: _)` instance.
        func stopRotating() {
            let kAnimationKey = "rotation"
            var currentState = CGFloat(0)

            // Get current state
            if let presentationLayer = layer.presentationLayer(), zValue = presentationLayer.valueForKeyPath("transform.rotation.z"){
                currentState = CGFloat(zValue.floatValue)
            }

            if self.layer.animationForKey(kAnimationKey) != nil {
                self.layer.removeAnimationForKey(kAnimationKey)
            }

            // Leave self as it was when stopped.
            layer.transform = CATransform3DMakeRotation(currentState, 0, 0, 1)
        }

    }

Use it like yourView.startRotating(duration: 1, clockwise: true), later to stop do yourView.stopRotating().

Upvotes: 7

Related Questions