NSWindow 宽度未使用 setFrame(frame, display, animate) 更新
Posted
技术标签:
【中文标题】NSWindow 宽度未使用 setFrame(frame, display, animate) 更新【英文标题】:NSWindow width not updated using setFrame(frame, display, animate) 【发布时间】:2019-03-26 12:11:36 【问题描述】:我是 macOS 的新手。我正在为 macos 开发一个应用程序,我希望用户在其中拥有侧面板,并且他可以根据需要隐藏/取消隐藏。
我使用split view
将我的屏幕分成 3 个部分。左右面板具有与视图成比例的宽度(不是拆分视图)。
我想要的是当用户隐藏左面板时,左面板应该隐藏自己,窗口的左锚应该向右移动,右锚应该保持在它的位置。
同样,如果用户隐藏右侧面板,右侧面板也应该被隐藏。窗口的右锚应该向左移动,左锚应该保持在它的位置。
当用户想要隐藏/取消隐藏左侧面板时,会调用以下函数。
guard let window = self.view.window else
return
var frame = window.frame
if window.isZoomed
if leftPane.contentView!.isHidden
self.leftPane.isHidden = false
self.leftPane.contentView?.isHidden = false
else
self.leftPane.contentView?.isHidden = true
else
if leftPaneHidden
self.leftPane.isHidden = false
frame = NSRect(x: (frame.origin.x - leftPane.frame.size.width), y: frame.origin.y, width: (frame.size.width + leftPane.frame.size.width), height: frame.size.height)
leftPaneHidden = false
else
self.leftPane.isHidden = true
frame = NSRect(x: (frame.origin.x + leftPane.frame.size.width), y: frame.origin.y, width: (frame.size.width - leftPane.frame.size.width), height: frame.size.height)
leftPaneHidden = true
self.view.window?.setFrame(frame, display: true, animate: true)
我希望隐藏左侧面板,因为它可以在 notability 应用中使用。
【问题讨论】:
澄清一下,您是说要缩小封闭窗口吗? 我想隐藏面板。确保没有其他面板扩展其宽度。我不希望它像 xcode 一样工作。我希望它像知名应用一样工作。 假设窗口大小为 100。面板每个宽度为 15。如果一次隐藏一个面板,则窗口宽度应为 85。如果两个面板都隐藏,则窗口宽度应为 70。 查看我的示例。照原样,它应该做你想做的事。 (而且,如果它对您有帮助并且您不介意,请检查并投票!) 【参考方案1】:如果您确实想要缩小/扩大窗口,这里有一个工作演示。如果您希望它以 Xcode 的方式工作,请删除框架的混乱。它以编程方式实现,因此我不必描述情节提要,但您可以轻松地使用情节提要做同样的事情。左右视图中唯一的代码设置了背景颜色,以便您可以看到它的工作原理。
SplitViewController:
class MainSplitViewController: NSSplitViewController
weak var leftItem: NSSplitViewItem?
weak var rightItem: NSSplitViewItem?
convenience init(identifier: NSUserInterfaceItemIdentifier)
self.init()
splitView.identifier = identifier
splitView.wantsLayer = true
splitView.layer?.backgroundColor = NSColor.darkGray.cgColor
splitView.dividerStyle = .thin
let vcL = SubViewController(NSView(), backgroundColor: .red)
let vcM = MainViewController(MainView(self), backgroundColor: .green)
let vcR = SubViewController(NSView(), backgroundColor: .blue)
vcL.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
vcM.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
vcR.view.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
let sidebarItem = NSSplitViewItem(viewController: vcL)
sidebarItem.canCollapse = true
sidebarItem.holdingPriority = NSLayoutConstraint.Priority(NSLayoutConstraint.Priority.defaultLow.rawValue + 1)
addSplitViewItem(sidebarItem)
leftItem = sidebarItem
let mainItem = NSSplitViewItem(viewController: vcM)
addSplitViewItem(mainItem)
let inspItem = NSSplitViewItem(viewController: vcR)
inspItem.canCollapse = true
inspItem.holdingPriority = NSLayoutConstraint.Priority(NSLayoutConstraint.Priority.defaultLow.rawValue + 1)
addSplitViewItem(inspItem)
rightItem = inspItem
中间视图,带有切换侧视图的按钮:
class MainView: NSView, DebugHelper
weak var splitViewController: MainSplitViewController?
func labeledButton(_ stringValue: String = "") -> NSButton
let button = NSButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: 28.0)
button.bezelStyle = NSButton.BezelStyle.rounded
button.title = stringValue
return button
private func adjustWindowFrame(_ item: NSSplitViewItem, left: Bool)
let view = item.viewController.view
let frame = window!.frame
if item.isCollapsed
let minX = left ? frame.minX - view.frame.width : frame.minX
let newFrame = NSRect(x: minX, y: frame.minY, width: frame.width + view.frame.width, height: frame.height)
window!.setFrame(newFrame, display: true)
else
let minX = left ? frame.minX + view.frame.width : frame.minX
let newFrame = NSRect(x: minX, y: frame.minY, width: frame.width - view.frame.width, height: frame.height)
window!.setFrame(newFrame, display: true)
item.isCollapsed = !item.isCollapsed
@objc func collapseLeft(_ sender: Any)
guard let item = splitViewController?.leftItem else return
adjustWindowFrame(item, left: true)
@objc func collapseRight(_ sender: Any)
guard let item = splitViewController?.rightItem else return
adjustWindowFrame(item, left: false)
convenience init(_ parent: MainSplitViewController)
self.init(frame: .zero)
splitViewController = parent
translatesAutoresizingMaskIntoConstraints = false
let lButton = labeledButton("Collapse Left")
addSubview(lButton)
lButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20).isActive = true
lButton.centerXAnchor.constraint(equalTo: centerXAnchor, constant: -100).isActive = true
lButton.action = #selector(collapseLeft)
lButton.target = self
let rButton = labeledButton("Collapse Right")
addSubview(rButton)
rButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20).isActive = true
rButton.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 100).isActive = true
rButton.action = #selector(collapseRight)
rButton.target = self
class MainViewController: NSViewController
convenience init(_ view: NSView, backgroundColor: NSColor = .white)
self.init()
self.view = view
self.view.wantsLayer = true
self.view.layer?.backgroundColor = backgroundColor.cgColor
【讨论】:
以上是关于NSWindow 宽度未使用 setFrame(frame, display, animate) 更新的主要内容,如果未能解决你的问题,请参考以下文章
我可以在同一个视图上使用 setFrame 和 autolayout 吗?
setTranslatesAutoresizingMaskIntoConstraints和setFrame组合使用导致的异常