简体   繁体   中英

How do I animate a NSWindow's size change when it gets resized by Auto Layout?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM