Godfather
Godfather

Reputation: 4330

animate rotation UIImageView in swift

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

Upvotes: 41

Views: 65937

Answers (11)

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

Upvotes: 0

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

Upvotes: 49

IvanPavliuk
IvanPavliuk

Reputation: 1790

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

Upvotes: 9

Allen
Allen

Reputation: 229

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

Upvotes: 12

Gerard G
Gerard G

Reputation: 3463

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.

Upvotes: 14

NazarYavornytskyy
NazarYavornytskyy

Reputation: 359

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

Upvotes: 7

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

Upvotes: 18

KIDdAe
KIDdAe

Reputation: 2722

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

   }
}

Upvotes: 7

Usman Nisar
Usman Nisar

Reputation: 3081

Here is code to rotate imageview. swift 3.0

UIView.animate(withDuration:2.0, animations: {
            self.dropDownImage.transform = CGAffineTransform(rotationAngle: CGFloat(imageRotation))
        })

Upvotes: 26

Matt
Matt

Reputation: 7040

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)

Upvotes: 18

Jacob King
Jacob King

Reputation: 6159

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

    }

Upvotes: -2

Related Questions