2012-02-27 31 views
12

我有一個NSSplitView,它有兩個窗格 - 左邊的邊欄表格視圖和右邊的Web視圖。我也有一個代表組的操控性約束這樣的側邊欄:NSSplitView:在窗口調整大小期間控制分隔符的位置

- (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像素之間調整,這使用分配器手柄時工作正常。但是,當調整整個窗口的大小時,分隔符會被重新定位在這些限制之外。

有人知道如何控制這個嗎?

此外:如果我想存儲用戶對側欄寬度的選擇,是否可以將其讀取出來,保存到首選項文件並稍後恢復,或者是否有更直接的方法來執行這個?我注意到窗口的狀態在某些情況下得到保存 - 這是通常發生還是我必須控制它?

在此先感謝

阿恩

回答

4

你在找什麼是:調整大小後

- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize 

[sender frame]將是你NSSplitView的新的大小。然後,相應地重新調整您的子視圖。

+0

對我來說,這並不會在第一次調用setFrame時被調用。但是,如果我繼承NSSplitView並覆蓋resizeSubviewsWithOldSize,那麼確實會調用。 – 2016-09-14 19:00:01

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沒有最小值或最大值,不可摺疊。

0

我用

- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize 

但不是改變子視圖框,我用

[sender setPosition:360 ofDividerAtIndex:0]; //or whatever your index and position should be 

更改框架沒有給我一致的結果。設定分隔器的位置。

2

解決這個的另一種方法是使用splitView:shouldAdjustSizeOfSubview:

我發現我的目的,這要簡單得多。例如,如果你想防止sidebarTableView小於你的最小寬度,那麼你可以做這樣的事情(假設你在視圖控制器/委託上使sidebarTableView成爲一個插座)。

- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview 
{ 
    if ((subview==self.sidebarTableView) && subview.bounds.size.width<=175) { 
     return NO; 
    } 
    return YES; 
} 
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的罰款,並比更清潔其他方法,因爲它是最小的代碼和約束不重複。

0

也許爲晚會太晚了,但這是我執行resizeSubviewWithOldSize:。在我的項目中,我需要一個縱向可調整大小的NSplitView,左視圖寬度在100.0到300.0之間;不考慮「摺疊」。您應該注意子視圖的所有可能的維度。

-(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); 
    } 
} 
3

我最初實施的NSSplitView委託功能,結束了一個大量的代碼嘗試做這麼簡單的東西作爲限制的最小尺寸爲每個拆分視圖側面。

然後我改變了我的方法,發現了一個乾淨而簡單的解決方案。我只需在NSView上爲NSSplitView的一側設置一個自動佈局常量,寬度爲(> =我想要的最小尺寸)。我在另一邊也做了同樣的事情。有了這兩個簡單的限制,NSSplitView可以完美工作,無需委託電話。

0

我已經通過將上的holdingPriority設置爲Interface Builder中固定端的Required(1000)來實現此行爲。然後,您可以通過在底層NSView上設置約束來控制固定端的寬度。

0

我只需要做到這一點,並提出這種方法比以前的例子更簡單。此代碼假定有NSSplitView容器左側和右側NSScrollViews的IBOutlets以及左側和右側視圖的最小大小的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]; 
    } 
}