'Rotate UIButton 360 degrees

I've been trying to run an animation that rotates my UIButton 360 degrees using this code:

UIView.animateWithDuration(3.0, animations: {
  self.vineTimeCapButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*2))
  self.instagramTimeCapButton.transform = CGAffineTransformMakeRotation(CGFloat(M_PI*2))
})

However, it doesn't rotate 360 degrees because the UIButton is already at that location.

How can I rotate my UIButton 360 degrees?



Solution 1:[1]

You can use a trick: start rotating with 180 degrees first and then rotate with 360 degrees. Use 2 animations with delay. Try this.

UIView.animate(withDuration: 0.5) {
    self.view.transform = CGAffineTransform(rotationAngle: .pi)
}

UIView.animate(
    withDuration: 0.5,
    delay: 0.45,
    options: UIView.AnimationOptions.curveEaseIn
) {
    self.view.transform = CGAffineTransform(rotationAngle: 2 * .pi)
}

Solution 2:[2]

As discussed here, you can also use a CAAnimation. This code applies one full 360 rotation:

Swift 3

let fullRotation = CABasicAnimation(keyPath: "transform.rotation")
fullRotation.delegate = self
fullRotation.fromValue = NSNumber(floatLiteral: 0)
fullRotation.toValue = NSNumber(floatLiteral: Double(CGFloat.pi * 2))
fullRotation.duration = 0.5
fullRotation.repeatCount = 1
button.layer.add(fullRotation, forKey: "360")

You will need to import QuartzCore:

import QuartzCore

And your ViewController needs to conform to CAAnimationDelegate:

class ViewController: UIViewController, CAAnimationDelegate {

}

Solution 3:[3]

Swift 4: Animation nested closure is better than animation delay block.

UIView.animate(withDuration: 0.5, animations: { 
  button.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi))) 
 }) { (isAnimationComplete) in

       // Nested Block
UIView.animate(withDuration: 0.5) { 
   button.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi * 2)))
       }    
}

Solution 4:[4]

Swift 4 version that allows you to rotate the same view infinite times:

UIView.animate(withDuration: 0.5) {
  self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
}

if you want to rotate 360°:

UIView.animate(withDuration: 0.5) {
  self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
  self.yourButton.transform = self.yourButton.transform.rotated(by: CGFloat.pi)
}

Solution 5:[5]

in Swift 3 :

UIView.animate(withDuration:0.5, animations: { () -> Void in
  button.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
})

UIView.animate(withDuration: 0.5, delay: 0.45, options: .curveEaseIn, animations: { () -> Void in
  button.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * 2))
}, completion: nil)

Solution 6:[6]

You can use a little extension based on CABasicAnimation (Swift 4.x):

extension UIButton {
    func rotate360Degrees(duration: CFTimeInterval = 1.0, completionDelegate: AnyObject? = nil) {
        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(.pi * 2.0)
        rotateAnimation.duration = duration

        if let delegate: AnyObject = completionDelegate {
            rotateAnimation.delegate = delegate as? CAAnimationDelegate
        }
        self.layer.add(rotateAnimation, forKey: nil)
    }
}

Usage:

For example we can start to make a simple button:

let button = UIButton()
button.frame = CGRect(x: self.view.frame.size.width/2, y: 150, width: 50, height: 50)
button.backgroundColor = UIColor.red
button.setTitle("Name your Button ", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)

Then we can build its selector:

@objc func buttonAction(sender: UIButton!) {
        print("Button tapped")
        sender.rotate360Degrees()
}

Solution 7:[7]

You can also try to implement an extension which will simplify things if you need to do it multiple time

extension UIView {
    
    func rotate360Degrees(duration: CFTimeInterval = 1, repeatCount: Float = .infinity) {
        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = CGFloat(Double.pi * 2)
        rotateAnimation.isRemovedOnCompletion = false
        rotateAnimation.duration = duration
        rotateAnimation.repeatCount = repeatCount
        layer.add(rotateAnimation, forKey: nil)
    }
    
    // Call this if using infinity animation
    func stopRotation () {
        layer.removeAllAnimations()
    }
}

Solution 8:[8]

Swift 5. Try this, it worked for me

UIView.animate(withDuration: 3) {
  self.yourButton.transform = CGAffineTransform(rotationAngle: .pi)
  self.yourButton.transform = CGAffineTransform(rotationAngle: .pi * 2)
 }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 aheze
Solution 2 Kuldeep
Solution 3
Solution 4
Solution 5 budiDino
Solution 6
Solution 7 Abhishek Maurya
Solution 8 nadeem ahmad