Consider an NSWindow
whose height is controlled by a set of complex constraints, and I want to have the window's resizing animated whenever the constraints cause the window to get resized.
As a simply example, let's just assume that the Window has no subviews, and instead of a set of complex constraints we just use a single constraint that directly controls the window's content view's height.
Now, when I change the constraint, the window gets implicitly resized. But since I do not set the window's frame myself (in the complex model I can't predict the new size!), I cannot use the animated window resize function that's commonly used for animating window resizes. So, how do I get the resize animated when Auto Layout has control over the resizing?
Here's an example in Swift. To use it, simply create a new plain "Cocoa App" project in Xcode and then replace the following function in AppDelegate:
func applicationDidFinishLaunching(_ aNotification: Notification) {
let view = self.window.contentView!
// Add a height constraint to the window's view
let heightConstraint = NSLayoutConstraint.init(item: view, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: view.frame.size.height)
view.addConstraint(heightConstraint)
// Resize the window after a brief delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// Now change the constraint, which results in the window getting resized instantly.
// But I would like the window's size change animated. How do I accomplish this?
NSAnimationContext.runAnimationGroup(
{ context in
context.duration = 0.5
heightConstraint.constant = heightConstraint.constant + 100
},
completionHandler:nil
)
}
}
there is a proxy object for constraints. instead of changing the constraint's constant, set animator()'s constant. It will animate. After animation end's call self.layoutSubtreeIfNeeded()
to update the constraints.
NSAnimationContext.runAnimationGroup({ context in
context.duration = 0.5
context.allowsImplicitAnimation = true
heightConstraint.animator().constant = heightConstraint.constant + 100
}, completionHandler: {
view.layoutSubtreeIfNeeded()
})