调整窗口大小以查看故事板中的控制器大小

时间:2014-12-20 07:30:43

标签: macos cocoa storyboard appkit

我正在OSX 10.10上使用Xcode 6.1.1。我正在为Mac应用程序试用故事板。我有一个使用新NSTabViewControllerTabStyleToolbar tabStyle的NSTabViewController,它被设置为窗口控制器的默认视图控制器。 如何根据当前选定的视图控制器调整窗口大小?

是否可以完全在Interface Builder中完成? 这是我的故事板的样子: storyboard

4 个答案:

答案 0 :(得分:12)

自动布局答案是其中的一半。您需要在每个选项卡的ViewController中将preferredContentSize设置为拟合大小(如果您希望选项卡大小为满足所有约束的最小大小)。

override func viewWillAppear() {
        super.viewWillAppear()
        preferredContentSize = view.fittingSize
}

如果您的约束导致下面的问题首先尝试使用固定大小,下面的示例在选项卡项的视图控制器的viewWillAppear函数中设置此项(此处使用Swift,但Objective-C版本同样有效)。

override func viewWillAppear() {
        super.viewWillAppear()
        preferredContentSize = NSSize(width: 400, height: 280)
}

如果可行,请调整您的约束以找出正在进行的操作

答案 1 :(得分:4)

此工具栏样式的解决方案'选项卡视图控制器会动画并支持良好的交叉渐变效果。在故事板设计器中,添加' TabViewController'在NSTabViewController的自定义类名称字段中。不要忘记为每个viewController分配一个标题,这用作键值。

import Cocoa

class TabViewController: NSTabViewController {

    private lazy var tabViewSizes: [String : NSSize] = [:]

    override func viewDidLoad() {
        // Add size of first tab to tabViewSizes
        if let viewController = self.tabViewItems.first?.viewController, let title = viewController.title {
            tabViewSizes[title] = viewController.view.frame.size
        }
        super.viewDidLoad()
    }

    override func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions, completionHandler completion: (() -> Void)?) {

        NSAnimationContext.runAnimationGroup({ context in
            context.duration = 0.5
            self.updateWindowFrameAnimated(viewController: toViewController)
            super.transition(from: fromViewController, to: toViewController, options: [.crossfade, .allowUserInteraction], completionHandler: completion)
        }, completionHandler: nil)
    }

    func updateWindowFrameAnimated(viewController: NSViewController) {

        guard let title = viewController.title, let window = view.window else {
            return
        }

        let contentSize: NSSize

        if tabViewSizes.keys.contains(title) {
            contentSize = tabViewSizes[title]!
        }
        else {
            contentSize = viewController.view.frame.size
            tabViewSizes[title] = contentSize
        }

        let newWindowSize = window.frameRect(forContentRect: NSRect(origin: NSPoint.zero, size: contentSize)).size

        var frame = window.frame
        frame.origin.y += frame.height
        frame.origin.y -= newWindowSize.height
        frame.size = newWindowSize
        window.animator().setFrame(frame, display: false)
    }
}

答案 2 :(得分:1)

如果您的故事板选项卡视图(macOS 11.1、Xcode 12.3)中有自动布局约束,则包含工具栏样式选项卡视图控制器的窗口确实无需任何代码即可调整大小。我还没有尝试过其他样式的选项卡视图控制器。

如果您想像在 Finder 中那样使用动画调整大小,只需在选项卡视图控制器中添加一个覆盖就足够了。它将使用系统计算的调整大小动画时间调整窗口大小,并在调整大小动画期间隐藏选项卡视图:

class PreferencesTabViewController: NSTabViewController {

    override func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions = [], completionHandler completion: (() -> Void)? = nil) {

        guard let window = view.window else {
            super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
            return
        }

        let fromSize = window.frame.size
        let toSize = window.frameRect(forContentRect: toViewController.view.frame).size
        let widthDelta = toSize.width - fromSize.width
        let heightDelta = toSize.height - fromSize.height
        var toOrigin = window.frame.origin
        toOrigin.x += widthDelta / 2
        toOrigin.y -= heightDelta
        let toFrame = NSRect(origin: toOrigin, size: toSize)

        NSAnimationContext.runAnimationGroup { context in
            context.duration = window.animationResizeTime(toFrame)
            view.isHidden = true
            window.animator().setFrame(toFrame, display: false)
            super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
        } completionHandler: { [weak self] in
            self?.view.isHidden = false
        }

    }

}

如果您使用的是 5.3 之前的 Swift 版本,请调整闭包语法。

答案 3 :(得分:-4)

使用自动布局。为您的视图设置显式大小约束。或者,当您在每个选项卡视图项目的视图中输入UI后,设置内部约束,以便它们强制视图为您想要的大小。