【问题标题】:How to show only Toolbar on NSWindow如何在 NSWindow 上仅显示工具栏
【发布时间】:2015-10-30 09:34:19
【问题描述】:

我是 swift 和 Xcode 的新手:我正在尝试编写一个可可应用程序,但似乎无法弄清楚如何完全隐藏我的 NSWindow 的内容。我在 Xcode 版本 6.3.2 上使用 Swift;使用故事板设计的 UI。

背景:我正在设计一个应用程序,其中一些控件在窗口的工具栏中显示给用户。其中一个控件是用于切换内容的显示按钮:单击该按钮允许用户展开工具栏下方的窗口内容,以查看一些带有其他详细信息的视图。再次单击显示按钮将折叠窗口内容,隐藏窗口中包含的视图并再次仅显示工具栏。当应用程序加载时,只应显示工具栏 - 所有窗口内容都应隐藏,因为此时它们无关紧要。

在我的WindowController.swift 中,我有:

class WindowController: NSWindowController, NSToolbarDelegate {

override func windowDidLoad() {
    super.windowDidLoad()

    window?.hideContents()
}

我已经定义了一个 NSWindow 扩展;在NSWindow.swift 我有:

private let TOOLBAR_WIDTH:CGFloat = 350.0
private let TOOLBAR_HEIGHT:CGFloat = 75.0
private let CONTENT_WIDTH:CGFloat = 800.0
private let CONTENT_HEIGHT:CGFloat = 600.0

public extension NSWindow {

    private var screenHeight : CGFloat {
       get {
           return NSScreen.mainScreen()!.frame.height
       }
    }

    public func hideContents() {
        let view = contentView as! NSView
        view.hidden = true
        view.needsDisplay = true

        collapseContentsFrame()
    }

    private func collapseContentsFrame() {

        var newFrame = NSRect(x:frame.origin.x, y:screenHeight, width: TOOLBAR_WIDTH, height: TOOLBAR_HEIGHT )

        setFrame( newFrame, display: false, animate: false )
    }

    public func showContents() {
        let view = contentView as! NSView
        view.hidden = false
        view.needsDisplay = true

        expandContentsFrame()
    }

    private func expandContentsFrame() {

        var newFrame = NSRect(x: frame.origin.x, y: screenHeight, width: CONTENT_WIDTH, height: CONTENT_HEIGHT )

        setFrame( newFrame, display: true, animate: false )
    }
}

这种工作方式:它隐藏了窗口中包含的视图的内容,并将框架缩小到与工具栏几乎相同的大小。但是,工具栏下方仍然显示一个宽的空矩形 - 看起来窗口的框架没有正确调整大小(由于我没有权限,无法发布图像)。我已尝试调整新框架上的值,但似乎无法消除工具栏下方显示的额外空间。

在情节提要中,窗口内容链接到 TabViewController - 不确定这是否与它有关。任何建议/见解将不胜感激。

【问题讨论】:

  • 所以你只想要一个 NSToolbar 大小的窗口?你能解释一下你为什么要这样做吗,因为工具栏是用来修改内容视图中的内容的。
  • 卢卡斯,感谢您的回复。根据您的建议,我已编辑问题以提供更多详细信息。
  • 您是否在正在显示的视图控制器中使用自动布局?意思是,有什么东西可以阻止内容折叠吗?
  • 啊,很好地抓住了卢卡斯。我在视图中确实有一些限制,这导致工具栏下的一些空白区域。我注意到一些有趣的事情:如果我用普通的 NSViewController 替换 NSTabViewController,一切都会完美,但是当我用 NSTabViewController 交换控制器时(我没有添加任何约束),我在工具栏下得到一个小间隙。任何想法是什么原因造成的?有什么建议可以在视图可见但视图隐藏时保持约束?
  • 如果 NSTabViewController 是您的问题,您应该保留内容视图的引用,然后在折叠时将其从窗口中移除,而不是隐藏。

标签: xcode swift cocoa nswindow nstoolbar


【解决方案1】:

感谢 Max 和 Lucas 的建议。我尝试删除内容视图,在我的 WindowController 中保留对它的引用,然后在窗口展开时将其再次添加回窗口。虽然这解决了手头的问题,但它给我带来了新问题:我以编程方式从工具栏调用 segue,但如果窗口没有内容视图,则此 segue 调用崩溃。

最终对我有用的解决方案涉及在隐藏窗口内容时暂时删除内容视图上的约束,然后在内容视图变得可见时再次添加约束。供参考(以防其他人将来遇到这种情况),这是我所做的:

在我的 WindowController.swift 中:

class WindowController: NSWindowController, NSToolbarDelegate {

    var mainWindow:Window {
        get {
            return window! as! Window
        }
    }

    override func windowDidLoad() {

        super.windowDidLoad()

        mainWindow.hideContents()
    }
}

在自定义的 NSWindow 子类中:

import Cocoa

class Window : NSWindow {

    private let TOOLBAR_WIDTH:CGFloat = 350.0
    private let TOOLBAR_HEIGHT:CGFloat = 75.0
    private let CONTENT_WIDTH:CGFloat = 800.0
    private let CONTENT_HEIGHT:CGFloat = 600.0

    private var constraints:[NSLayoutConstraint] = [NSLayoutConstraint]()

    override init( contentRect: NSRect,
        styleMask windowStyle: Int,
        backing bufferingType: NSBackingStoreType,
        defer deferCreation: Bool) {

        super.init( contentRect: contentRect, styleMask: windowStyle, backing: bufferingType, defer: deferCreation )
    }

    required init?( coder: NSCoder ) {
        super.init( coder: coder )
    }

    private var screenHeight : CGFloat {
        get {
            return NSScreen.mainScreen()!.frame.height
        }
    }

    private var view : NSView {
        get {
            return contentView as! NSView
        }
    }

    func hideContents() {

        view.hidden = true

        collapseContentsFrame()

        removeConstraints()
    }

    private func collapseContentsFrame() {
        var newFrame = NSRect(x:frame.origin.x, y:screenHeight, width: TOOLBAR_WIDTH, height: TOOLBAR_HEIGHT )
        setFrame( newFrame, display: false, animate: false )
    }

    private func removeConstraints() {
        constraints = view.constraints as! [NSLayoutConstraint]
        for constraint in constraints {
            view.removeConstraint( constraint )
        }
    }

    func showContents() {

        view.hidden = false

        expandContentsFrame()

        addConstraints()
    }

    private func expandContentsFrame() {
        var newFrame = NSRect(x: frame.origin.x, y: screenHeight, width: CONTENT_WIDTH, height: CONTENT_HEIGHT )
        setFrame( newFrame, display: true, animate: false )
    }

    private func addConstraints() {
        for constraint in constraints {
            view.addConstraint( constraint )
        }
    }
}

然后在我的 Main.storyboard 中,选择文档大纲中的 Window 节点并调出身份检查器 (CMD + ALT + 3)。然后我在“自定义类”字段中指定了我的“窗口”类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多