我有一个垂直NSSplitView,左侧是NSScrollView(NSOutlineView,源列表,没有标题视图),右侧是WebView。所有视图都有NSZeroRect
的初始帧。 NSSplitView,NSScrollView和WebView的自动调整遮罩处于关闭状态,NSSplitView用于使用自动布局填充窗口。我似乎无法强制NSSplitView分隔符位于给定位置;
[sv setPosition:250 ofDividerAtIndex:0];
简单地拒绝生效。虽然我的用例是初始位置,但我最终还是需要一个可以随时使用的解决方案,因为我没有使用nib / xib文件。
无论是否有上述setPosition:
调用,WebView都会获得NSSplitView的整个宽度。如果我将NSScrollView的初始帧设置为NSMakeRect(0, 0, 250, 0)
它可以工作。当然,这只是初始帧,这是不够好的(并且可以抵抗UI布局的变化)......我发现的所有东西早于自动布局,并且说你应该直接操作帧;由于这是自动布局,我怀疑这是个好主意......
但它更奇怪:如果我将分隔符样式设置为NSSplitViewDividerStyleThin
,即使NSMakeRect()
被忽略,NSScrollView也会被赋予NSSplitView的全宽,无论如何。
那为什么我不能设置NSSplitView的位置?
是因为位置是由自动布局决定的吗?在这种情况下,如何设置约束以强制左视图的宽度为给定宽度,让布局管理器运行以应用该约束,然后立即删除约束?我尝试覆盖NSSplitView的layout
和updateConstraints
来做,但是自动布局并不像我那样,当我再次尝试移动分隔线时没有效果并且崩溃!
或者我真的应该直接操纵NSSplitView子视图的框架,尽管Auto Layout最佳实践是什么?
是的,我已经在多次以及其他一些页面上阅读了每个类似的问题;它的所有建议要么不起作用,要么说setPosition:
应该神奇地工作。
这是OS X 10.11,但我需要一个可以追溯到10.7的解决方案。
以下Swift 2程序快速演示了我的意思。您可以使用appLaunched()
中的各种代码行来尝试各种效果。无论出于何种原因,我上面提到的奇怪的事情(左边的视图占据了分隔线样式为薄的所有空间)不会发生在这里。那是我对此感到困惑的其他事情......
感谢。
// 3 january 2016
// scratch program 17 august 2015
import Cocoa
import WebKit
var keepAliveMainwin: NSWindow? = nil
func appLaunched() {
let mainwin = NSWindow(
contentRect: NSMakeRect(0, 0, 320, 240),
styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask),
backing: NSBackingStoreType.Buffered,
`defer`: true)
let contentView = mainwin.contentView!
let splitView = NSSplitView(frame: NSZeroRect)
splitView.dividerStyle = NSSplitViewDividerStyle.Thin
splitView.vertical = true
splitView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(splitView)
let box1 = NSScrollView(frame: NSZeroRect)
let ov = NSOutlineView(frame: NSZeroRect)
ov.headerView = nil
ov.selectionHighlightStyle = NSTableViewSelectionHighlightStyle.SourceList
box1.documentView = ov
box1.translatesAutoresizingMaskIntoConstraints = false
splitView.addSubview(box1)
let box2 = WebView(frame: NSZeroRect)
box2.translatesAutoresizingMaskIntoConstraints = false
splitView.addSubview(box2)
let views: [String: NSView] = [
"splitView": splitView,
]
addConstraint(contentView, "H:|-[splitView]-|", views)
addConstraint(contentView, "V:|-[splitView]-|", views)
splitView.setPosition(50, ofDividerAtIndex: 0)
mainwin.cascadeTopLeftFromPoint(NSMakePoint(20, 20))
mainwin.makeKeyAndOrderFront(mainwin)
keepAliveMainwin = mainwin
}
func addConstraint(view: NSView, _ constraint: String, _ views: [String: NSView]) {
let constraints = NSLayoutConstraint.constraintsWithVisualFormat(
constraint,
options: [],
metrics: nil,
views: views)
view.addConstraints(constraints)
}
class appDelegate : NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(note: NSNotification) {
appLaunched()
}
func applicationShouldTerminateAfterLastWindowClosed(app: NSApplication) -> Bool {
return true
}
}
func main() {
let app = NSApplication.sharedApplication()
app.setActivationPolicy(NSApplicationActivationPolicy.Regular)
// NSApplication.delegate is weak; if we don't use the temporary variable, the delegate will die before it's used
let delegate = appDelegate()
app.delegate = delegate
app.run()
}
main()
答案 0 :(得分:3)
我遇到了同样的问题,我设法通过使用相同的参数调用setPosition:ofDividerAtIndex:
两次来解决它。也许它也适合你。
答案 1 :(得分:0)
对我有用的是,在调用setPosition
方法之后设置嵌套视图的框架:
let splitWidth = 600
splitViewController.splitView.setPosition(splitWidth, ofDividerAt: 0)
if let frame = splitViewController.splitViewItems.first?.viewController.view.frame {
splitViewController.splitViewItems.first?.viewController.view.setFrameSize(NSSize(width: splitWidth, height: frame.height))
}
此代码基于使用NSSplitViewController
,因此可能不适用于原始问题中描述的用例。