【问题标题】:How do I animate a NSWindow's size change when it gets resized by Auto Layout?当通过自动布局调整大小时,如何为 NSWindow 的大小更改设置动画?
【发布时间】:2021-04-08 14:35:56
【问题描述】:

考虑一个NSWindow,它的高度由一组复杂的约束控制,我希望在约束导致窗口调整大小时让窗口的大小调整动画。

作为一个简单的示例,我们假设 Window 没有子视图,而不是一组复杂的约束,我们只使用一个直接控制窗口内容视图高度的约束。 p>

现在,当我更改约束时,窗口会隐式调整大小。但是由于我自己没有设置窗口的框架(在复杂的模型中我无法预测新的大小!),我不能使用动画窗口调整大小的动画函数,该函数通常用于动画窗口调整大小。那么,当 Auto Layout 可以控制调整大小时,如何使调整大小动画化?

这是 Swift 中的一个示例。要使用它,只需在 Xcode 中创建一个新的普通“Cocoa App”项目,然后在 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
        )

    }
}

【问题讨论】:

    标签: objective-c swift macos autolayout nswindow


    【解决方案1】:

    有一个约束的代理对象。设置 animator() 的常量,而不是更改约束的常量。它会动画。动画结束后调用self.layoutSubtreeIfNeeded()更新约束。

    NSAnimationContext.runAnimationGroup({ context in
        context.duration = 0.5
        context.allowsImplicitAnimation = true
        heightConstraint.animator().constant = heightConstraint.constant + 100
    }, completionHandler: {
        view.layoutSubtreeIfNeeded()
    })
    

    【讨论】:

    • 这在我的简单示例中有效,但是如果我有一组复杂的约束,我没有像这样明确设置,但是由于添加或删除项目而导致窗口大小发生变化,我该怎么办来自 NSStackView 又由于连接约束而调整窗口大小?在这种情况下,修改因素是添加视图 - 在这种情况下我如何使用动画师?
    • 实际上,我刚刚意识到 NSViews 也提供了这样的animator 代理,所以我可以简单地调用stackView.animator.removeView 来使其工作,而不是调用stackView.removeView。 :)
    • 任何确认NSAnimatablePropertyContainer的东西都会有animator()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多