41

I'm trying to animate a rotation of 180 degrees of a UIImageView in Swift

    UIView.animateWithDuration(1.0, animations: { () -> Void in
        self.arrowImageView.transform = CGAffineTransformMakeRotation(CGFloat(180 * M_PI))
    }) { (succeed) -> Void in

    }

But isnt animating at all. I want to use animateWithDuration cause i want to make it back at some point using CGAffineTransformMakeIdentity

Using UIView animations works.

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(1)
    UIView.setAnimationCurve(UIViewAnimationCurve.EaseIn)
    let radians = CGFloat(180 * M_PI / 180)
    arrowImageView.transform = CGAffineTransformMakeRotation(radians)
    UIView.commitAnimations()
Jack
  • 13,571
  • 6
  • 76
  • 98
Godfather
  • 4,040
  • 6
  • 43
  • 70

11 Answers11

45

======= Extension for UIView =======

I found this answer from the Internet, and I test it, working perfectly fine. Hope this will help to any one, just change the UIView to your need such as, UIView, UIButton, UIImageView, etc. and access with the myUIView.rotate() function, here myUIView should be replace with your View name (IBOutlet -> name) with correct view type for extension. This is the link that I found this answer. And this method is easy and working!

=== SWIFT 3 / 4 ===

extension UIView{
    func rotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(double: M_PI * 2)
        rotation.duration = 1
        rotation.cumulative = true
        rotation.repeatCount = FLT_MAX
        self.layer.addAnimation(rotation, forKey: "rotationAnimation")
    }
}

suggested improvements. Thanks for all suggestions.

=== SWIFT 5 ===

extension UIView{
    func rotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(value: Double.pi * 2)
        rotation.duration = 1
        rotation.isCumulative = true
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.layer.add(rotation, forKey: "rotationAnimation")
    }
}

And then call that extension like follow:

self.your_UIViewOutletName_myUIView_here.rotate()
  • 12
    in swift 4, **M_PI** has been replace with **Double.pi**, and **FLT_MAX** replace with **Float.greatestFiniteMagnitude**, and **cumulative** with **isCumulative** :) – Rakshitha Muranga Rodrigo Feb 18 '18 at 03:58
  • please note that : This extension can be removed and can be modified only for functional usage, I have created this extension because you can use it every where with reusability and you can use this for any kind of View type : UIImageView, UIView.. etc. – Rakshitha Muranga Rodrigo Jun 24 '18 at 17:18
  • You most likely don't need to change the class that's being extended - the 3 classes you mentioned inherit from UIView as do many others – froggomad Jul 17 '19 at 04:29
25

Here is code to rotate imageview. swift 3.0

UIView.animate(withDuration:2.0, animations: {
            self.dropDownImage.transform = CGAffineTransform(rotationAngle: CGFloat(imageRotation))
        })
Usman Nisar
  • 3,031
  • 33
  • 41
18

First of all, if you want to rotate 180 degrees, that has to translate to radians. 180 degrees in radians is pi. 360 degrees would be 2 * pi. 180 * pi would make your animation spin around 90 times in one second and end up with the original orientation.

Secondly, I'm not sure why your code isn't working, but I know that the code below does work:

let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = M_PI
rotationAnimation.duration = 1.0

self.arrowImageView.layer.addAnimation(rotationAnimation, forKey: nil)
Matt
  • 6,993
  • 4
  • 29
  • 50
18

Updated swift 4.0 version:

    let rotation: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
    rotation.toValue = Double.pi * 2
    rotation.duration = 0.25 // or however long you want ...
    rotation.isCumulative = true
    rotation.repeatCount = Float.greatestFiniteMagnitude
    yourView.layer.add(rotation, forKey: "rotationAnimation")
14

Swift 5.0

extension UIImageView{
    func rotate() {
        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.toValue = NSNumber(value: Double.pi * 2)
        rotation.duration = 2
        rotation.isCumulative = true
        rotation.repeatCount = Float.greatestFiniteMagnitude
        self.layer.add(rotation, forKey: "rotationAnimation")
    }
}

Updating to @Rakshitha Muranga Rodrigo answer.

uplearned.com
  • 3,393
  • 5
  • 44
  • 59
12

You left out the / 180 on CGFloat(180 * M_PI). Try:

UIView.animate(withDuration: 1.0) {[weak self] in
    self?.arrowImageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))
}
Makalele
  • 7,431
  • 5
  • 54
  • 81
Allen
  • 219
  • 2
  • 12
9

90 degrees rotation

var shouldRotateArrow = false {
    didSet {
        rotateArrow()
    }
}

private func rotateArrow() {
    let angle: CGFloat = shouldRotateArrow ? .pi / 2 : 0
    UIView.animate(withDuration: Constants.arrowRotationDuration) {
        self.arrowImageView.transform = CGAffineTransform(rotationAngle: angle)
    }
}
IvanPavliuk
  • 1,460
  • 1
  • 21
  • 16
7

Be sure to be in the Main thread

DispatchQueue.main.async {
   UIView.animateWithDuration(1.0, animations: { () -> Void in
     self.arrowImageView.transform = CGAffineTransformMakeRotation(CGFloat(180 * M_PI))
   }) { (succeed) -> Void in

   }
}
KIDdAe
  • 2,714
  • 2
  • 22
  • 29
7

For me the best and shortest solution is (Swift 3/4):

self.YourImageView.transform = showing ? CGAffineTransform(rotationAngle: CGFloat.pi) : CGAffineTransform.identity

"showing" it's a value to determine is image rotated before or not - you can use your own logic here

Uma Madhavi
  • 4,851
  • 5
  • 38
  • 73
0

The below code helps to rotate the view continuously. UIView animate with .repeat mode repeat the animation indefinitely.

To start spinning ImageView -----------------

func startSpinning()  {
            UIView.animate(withDuration: 0.5, delay: 0, options: .repeat, animations: { () -> Void in
                self.gearImageView!.transform = self.gearImageView!.transform.rotated(by: .pi / 2)
                })
        }




To stop spin ImageView 
--------------------

func stopSpinning()  {
        self.gearImageView.layer.removeAllAnimations()
    }
  • Please don't post only code as an answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Tyler2P Nov 04 '21 at 16:55
-2

Try calling arrowImageView.layoutSubviews(), see below:

    UIView.animateWithDuration(1.0, animations: { () -> Void in
        self.arrowImageView.transform = CGAffineTransformMakeRotation(CGFloat(180 * M_PI))
        self.arrowImageView.layoutSubviews()
    }) { (succeed) -> Void in

    }
Jacob King
  • 6,025
  • 4
  • 27
  • 45