All the examples I could find online for UIViewPropertyAnimator
use views that are laid out by setting frame rather than using auto layout, which is how views are commonly laid out. When using auto layout, the view animates to the position I want, but afterwards I am not sure of how to set it back to its "model" position.
// Move a view that is constrained to the center of its superview
UIViewPropertyAnimator(duration: 1, curve: .linear) {
testView.center = CGPoint(x: 10, y: 10)
}.startAnimation()
It apparently adds some kind of constraint? I logged the container view's constraints before and after performing the animation:
CONSTRAINTS BEFORE:
view: [<NSLayoutConstraint:0x618000094f00 UIView:0x7fd764004050.centerX == UIView:0x7fd75fd00000.centerX (active)>, <NSLayoutConstraint:0x618000092de0 UIView:0x7fd764004050.centerY == UIView:0x7fd75fd00000.centerY (active)>]
CONSTRAINTS AFTER:
view: [<NSLayoutConstraint:0x618000094f00 UIView:0x7fd764004050.centerX == UIView:0x7fd75fd00000.centerX (active)>, <NSLayoutConstraint:0x618000092de0 UIView:0x7fd764004050.centerY == UIView:0x7fd75fd00000.centerY (active)>, <NSLayoutConstraint:0x6100000922a0 'UIView-Encapsulated-Layout-Height' UIView:0x7fd75fd00000.height == 667 (active)>, <NSAutoresizingMaskLayoutConstraint:0x610000092570 h=-&- v=-&- 'UIView-Encapsulated-Layout-Left' UIView:0x7fd75fd00000.minX == 0 (active, names: '|':UIWindow:0x7fd75fc07110 )>, <NSAutoresizingMaskLayoutConstraint:0x610000092890 h=-&- v=-&- 'UIView-Encapsulated-Layout-Top' UIView:0x7fd75fd00000.minY == 0 (active, names: '|':UIWindow:0x7fd75fc07110 )>, <NSLayoutConstraint:0x610000091670 'UIView-Encapsulated-Layout-Width' UIView:0x7fd75fd00000.width == 375 (active)>]
What's going on here? How should I handle the animation of views that are positioned with auto layout? Is Apple encouraging users to go back to frame-based layouts?
You can use
UIViewPropertyAnimator
with Auto Layout, but you need to modify the constraints instead of the view's frame and calllayoutIfNeeded()
inside of the closure.First example: Animate by modifying constraint
constant
Create a view in the Storyboard. Create a constraint to position the
centerX
of your view equal to the leading edge of the superview. Create an@IBOutlet
to that constraint and call itcenterXConstraint
. Similarly, create acenterYConstraint
that positions thecenterY
of your view equal to the top of its superview. Both of these constraints should haveconstant = 0
.Create
@IBOutlet
s to the constraints:Set the
constant
values of the constraint to the new position and then callview.layoutIfNeeded()
inside ofUIViewPropertyAnimator
:Second example: Animate by activating new constraints
Create a view in your Storyboard (for example
redView
) and create an@IBOutlet
to it in your code:Create
@IBOutlet
s to the constraints that control the position of your viewThen when it's time to animate:
UIViewPropertyAnimator
is an object that you can configure to control the animation in various ways. Here is a complete example that demonstrates:I made a tutorial for swift 4.1