den330 den330 - 13 days ago 4
iOS Question

What is the relation between auto-layout and viewAnimation?

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.5, animations: {
self.animateLabel.center.x += 30
})
}


Upper Label: Center for horizontal, and vertical.
Lower Label: Align leading to upper label, vertical space to upper label.

Then I put above code in ViewController to animate the upper label:

Then Run the simulator.

As you can see, these two label no longer aligned. Does that mean the auto-layout rule I set previously has been broken?
Yet, When I rotate the simulator, the upper label goes back to centre.
What is the relation between auto-layout and viewAnimation?

enter image description hereenter image description hereenter image description here

Answer

It isn't animation per se that is the issue, it is changing the view's frame directly that is causing your problem.

Essentially auto layout uses the constraints you have set to calculate the frame for each view. When you modify the frame directly (or implicitly by modifying the center property) then you are effectively overriding the results of the auto layout process and the view is repositioned.

Anything that causes the auto layout process to run again will result in the frame being recalculated according to the constraints. Rotating the device will cause such a recalculation, as would calling self.animateLabel.setNeedsLayout.

When you are using auto layout you should never reposition views directly; you should modify the constraints and then trigger auto layout to move the views.

Assuming you are using a storyboard, you should create an @IBOutlet for the upper label's horizontal center constraint. You can then animate this constraint:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.animateLabel.layoutIfNeeded()   // Ensure auto layout is complete
    self.labelCentreConstraint.Constant = 30
    UIView.animate(withDuration: 0.5, animations: {
        self.animateLabel.layoutIfneeded()   // Recalculate auto layout
    })
}
Comments