Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIView with auto layout constraints "jumps" before transform animation

I have a UIView constrained with Auto Layout. It's centered and has a constraint for Width and Height. When it appears, I'm applying a rotation transform to it.

Rotated View

When I hit that animation button, I want it to animate to a point higher on the screen, while rotating back to an "upright" position (ie with no rotation applied). So, I set a new translation transform:

let translation = CGAffineTransform(translationX: 1, y: -100)
UIView.animate(withDuration: 0.5, animations: {
   self.blueView.transform = translation
})

What I expect to see is the view rotate back to an upright position while translating upwards.

What I get instead is the view "jumping" to a point off to the right, and then animating upwards while rotating.

How can I fix this so that it doesn't "jump" before animating?

enter image description here

like image 623
bpapa Avatar asked Dec 13 '25 23:12

bpapa


1 Answers

You are seeing the jump because the blueView already has the rotation transform set when you animate the translation transform. That leads to unexpected results.

To make it work you combine the rotation and translation transform before the animation and then reset the transform animated:

To translate the blue view 100pt up and rotate it back to normal you do this:

  1. Add a transform to the blueView that translates it 100pt down and rotates it 45°
  2. Set the centerYAnchor constant to -100 to have the blueView in the correct position before the animation.
  3. Animate the blueView.transform = .identity to remove the transform animated

This is a working example:

class ViewController: UIViewController {

    let blueView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        blueView.backgroundColor = .blue
        view.addSubview(blueView)

        blueView.transform = CGAffineTransform(translationX: 0, y: 100).rotated(by: -CGFloat.pi / 4)

        let button = UIButton(type: .custom)
        button.setTitle("Animate", for: .normal)
        button.setTitleColor(.blue, for: .normal)
        button.addTarget(self, action: #selector(didPress), for: .touchUpInside)
        view.addSubview(button)

        blueView.translatesAutoresizingMaskIntoConstraints = false
        button.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            blueView.widthAnchor.constraint(equalToConstant: 20),
            blueView.heightAnchor.constraint(equalToConstant: 20),
            blueView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            blueView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -100),

            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -40)
            ])
    }

    @objc func didPress(sender: UIButton) {
        UIView.animate(withDuration: 0.5, animations: {
            self.blueView.transform = .identity
        })
    }
}
like image 105
joern Avatar answered Dec 16 '25 15:12

joern



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!