我有一个NSSplitView,它有两个窗格 - 左边是侧边栏表视图,右边是一个Web视图。我还有一个委托集,处理侧边栏的约束,如下所示:
- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex {
return 500.0f;
}
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
return 175.0f;
}
- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview {
return NO;
}
这意味着侧边栏只能在175到500像素之间调整大小,这在使用分隔符句柄时工作正常。但是当调整整个窗口的大小时,分隔符会从这些约束中重新定位。
有人知道如何控制这个吗?
此外:如果我想存储用户选择的侧边栏宽度,是否可以将其读出,将其保存到首选项文件并稍后恢复,或者是否有更直接的方法来执行此操作?我注意到窗口的状态在某些情况下会被保存 - 这通常会发生还是我必须控制它?
提前致谢
·阿尔
答案 0 :(得分:4)
您正在寻找的是:
- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
调整大小后, [sender frame]
将是NSSplitView
的新大小。然后相应地重新调整您的子视图。
答案 1 :(得分:3)
问题是,当调整NSSplitView本身的大小时,会调用-adjustSubviews
来完成工作,但它会忽略委托中的最小/最大约束!
但-setPosition:ofDividerAtIndex:
确实考虑了约束。
你需要做的就是将两者结合起来 - 这个例子假设NSSplitView只有2个视图:
- (CGFloat)splitView:(NSSplitView*)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
return 300;
}
- (CGFloat)splitView:(NSSplitView*)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex {
return (splitView.vertical ? splitView.bounds.size.width : splitView.bounds.size.height) - 500;
}
- (void)splitView:(NSSplitView*)splitView resizeSubviewsWithOldSize:(NSSize)oldSize {
[splitView adjustSubviews]; // Use default resizing behavior from NSSplitView
NSView* view = splitView.subviews.firstObject;
[splitView setPosition:(splitView.vertical ? view.frame.size.width : view.frame.size.height) ofDividerAtIndex:0]; // Force-apply constraints afterwards
}
这似乎在OS X 10.8,10.9和10.10上运行良好,并且比其他方法更清晰,因为它的代码最小且约束不重复。
答案 2 :(得分:3)
我最初实现了NSSplitView
委托函数,并最终使用了大量代码来尝试做一些简单的操作,例如限制每个拆分视图边的最小大小。
然后我改变了我的方法,找到了一个干净且非常简单的解决方案。我只是为NSView
的一侧NSSplitView
上的宽度(> =我想要的最小尺寸)设置了一个自动布局常量。我在另一边做了同样的事情。通过这两个简单约束,NSSplitView
可以完美地工作,而无需委托调用。
答案 3 :(得分:2)
另一种解决方法是使用splitView:shouldAdjustSizeOfSubview:
我发现这对我来说更简单。
例如,如果你想阻止sidebarTableView小于你的175最小宽度,那么你可以做这样的事情(假设你在视图控制器/委托上做了sidebarTableView一个插座);
- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview
{
if ((subview==self.sidebarTableView) && subview.bounds.size.width<=175) {
return NO;
}
return YES;
}
答案 4 :(得分:1)
以下是我-splitView:resizeSubviewsWithOldSize:
的实现:
-(void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize {
if (![splitView isSubviewCollapsed:self.rightView] &&
self.rightView.frame.size.width < 275.0f + DBL_EPSILON) {
NSSize splitViewFrameSize = splitView.frame.size;
CGFloat leftViewWidth = splitViewFrameSize.width - 275.0f - splitView.dividerThickness;
self.leftView.frameSize = NSMakeSize(leftViewWidth,
splitViewFrameSize.height);
self.rightView.frame = NSMakeRect(leftViewWidth + splitView.dividerThickness,
0.0f,
275.0,
splitViewFrameSize.height);
} else
[splitView adjustSubviews];
}
就我而言,rightView
是两个子视图中的第二个,它是可折叠的,最小宽度为275.0。 leftView
没有最小值或最大值,并且不可折叠。
答案 5 :(得分:0)
我用过
- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
但是我没有改变子视图框架,而是使用了
[sender setPosition:360 ofDividerAtIndex:0]; //or whatever your index and position should be
更改框架并没有给我一致的结果。设置分隔符的位置确实如此。
答案 6 :(得分:0)
对于派对来说可能为时已晚,但这是我对resizeSubviewWithOldSize:
的实施。在我的项目中,我需要一个垂直可调整大小的NSplitView,其leftView宽度在100.0和300.0之间;没有&#39;倒塌&#39;考虑到了。您应该处理子视图的所有可能维度。
-(void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize {
if (self.leftView.frame.size.width >= kMaxLeftWidth) {
NSSize splitViewFrameSize = splitView.frame.size;
CGFloat leftViewWidth = kMaxLeftWidth;
CGFloat rightViewWidth = splitViewFrameSize.width - leftViewWidth - splitView.dividerThickness;
self.leftView.frameSize = NSMakeSize(leftViewWidth,
splitViewFrameSize.height);
self.rightView.frame = NSMakeRect(leftViewWidth + splitView.dividerThickness,
0.0f,
rightViewWidth,
splitViewFrameSize.height);
} else if (self.leftView.frame.size.width <= kMinLeftWidth) {
NSSize splitViewFrameSize = splitView.frame.size;
CGFloat leftViewWidth = kMinLeftWidth;
CGFloat rightViewWidth = splitViewFrameSize.width - leftViewWidth - splitView.dividerThickness;
self.leftView.frameSize = NSMakeSize(leftViewWidth,
splitViewFrameSize.height);
self.rightView.frame = NSMakeRect(leftViewWidth + splitView.dividerThickness,
0.0f,
rightViewWidth,
splitViewFrameSize.height);
} else {
NSSize splitViewFrameSize = splitView.frame.size;
CGFloat leftViewWidth = self.leftView.frame.size.width;
CGFloat rightViewWidth = splitViewFrameSize.width - leftViewWidth - splitView.dividerThickness;
self.leftView.frameSize = NSMakeSize(leftViewWidth,
splitViewFrameSize.height);
self.rightView.frame = NSMakeRect(leftViewWidth + splitView.dividerThickness,
0.0f,
rightViewWidth,
splitViewFrameSize.height);
}
}
答案 7 :(得分:0)
我通过在Interface Builder中将固定端的holdingPriority
NSSplitViewItem
设置为Required(1000)来实现此行为。然后,您可以通过在基础NSView
上设置约束来控制固定边的宽度。
答案 8 :(得分:0)
我只需要这样做,并想出了这个比以前的例子简单一点的方法。此代码假定NSSplitView容器的左侧和右侧NSScrollViews有IBOutlet,左侧和右侧视图的最小大小为CGFloat常量。
#pragma mark - NSSplitView sizing override
//------------------------------------------------------------------------------
// This is implemented to ensure that when the window is resized that our main table
// remains at it's smallest size or larger (the default proportional sizing done by
// -adjustSubviews would size it smaller w/o -constrainMinCoordiante being called).
- (void) splitView: (NSSplitView *)inSplitView resizeSubviewsWithOldSize: (NSSize)oldSize
{
// First, let the default proportional adjustments take place
[inSplitView adjustSubviews];
// Then ensure that our views are at least their min size
// *** WARNING: this does not handle allowing the window to be made smaller than the total of the two views!
// Gather current sizes
NSSize leftViewSize = self.leftSideView.frame.size;
NSSize rightViewSize = self.rightSideView.frame.size;
NSSize splitViewSize = inSplitView.frame.size;
CGFloat dividerWidth = inSplitView.dividerThickness;
// Assume we don't have to resize anything
CGFloat newLeftWidth = 0.0f;
// Always adjust the left view first if we need to change either view's size
if( leftViewSize.width < kLeftSplitViewMinSize )
{
newLeftWidth = kLeftSplitViewMinSize;
}
else if( rightViewSize.width < kRightSplitViewMinSize )
{
newLeftWidth = splitViewSize.width - (kRightSplitViewMinSize + dividerWidth);
}
// Do we need to adjust the size?
if( newLeftWidth > 0.0f )
{
// Yes, do so by setting the left view and setting the right view to the space left over
leftViewSize.width = newLeftWidth;
rightViewSize.width = splitViewSize.width - (newLeftWidth + dividerWidth);
// We also need to set the origin of the right view correctly
NSPoint origin = self.rightSideView.frame.origin;
origin.x = splitViewSize.width - rightViewSize.width;
[self.rightSideView setFrameOrigin: origin];
// Set the the ajusted view sizes
leftViewSize.height = rightViewSize.height = splitViewSize.height;
[self.leftSideView setFrameSize: leftViewSize];
[self.rightSideView setFrameSize: rightViewSize];
}
}