2012-02-27 30 views
12

Tôi có một NSSplitView có hai ô - một khung nhìn thanh bên ở bên trái và chế độ xem web ở bên phải. Tôi cũng có một bộ đại biểu đó là xử lý những khó khăn trong thanh bên như thế này:NSSplitView: Kiểm soát vị trí chia trong khi đổi kích thước cửa sổ

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

Nó có nghĩa là thanh bên chỉ có thể được thay đổi kích cỡ giữa 175 và 500 pixel và điều này hoạt động tốt khi sử dụng tay cầm chia. Nhưng khi thay đổi kích thước toàn bộ cửa sổ, bộ chia được định vị lại từ những ràng buộc này.

Có ai biết cách kiểm soát điều này không?

Ngoài ra: Nếu tôi muốn lưu trữ lựa chọn chiều rộng thanh bên của người dùng, bạn nên đọc nó, lưu nó vào tệp tùy chọn và khôi phục sau hoặc có cách làm thẳng hơn điều này? Tôi nhận thấy rằng trạng thái của cửa sổ được lưu trong một số trường hợp - điều này thường xảy ra hay tôi phải kiểm soát nó?

Cảm ơn trước

Arne

Trả lời

4

Những gì bạn đang tìm kiếm là:

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

[sender frame] sẽ được kích thước mới của NSSplitView của bạn sau khi thay đổi kích thước. Sau đó, chỉ cần điều chỉnh các bản xem trước của bạn cho phù hợp.

+0

đối với tôi, điều này không được gọi là lần đầu tiên setFrame: được gọi. Tuy nhiên, nếu tôi phân lớp NSSplitView và ghi đè resizeSubviewsWithOldSize, nó sẽ được gọi. –

1

Dưới đây là thực hiện của tôi -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]; 
} 

Trong trường hợp của tôi, rightView là lần thứ hai trong hai subviews, đó là đóng mở với chiều rộng tối thiểu là 275,0. leftView không có giá trị tối thiểu hoặc tối đa và không thể thu gọn.

0

tôi đã sử dụng

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

nhưng thay vì thay đổi khung subview, tôi sử dụng

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

Thay đổi khung đã không cho tôi kết quả phù hợp. Đặt vị trí của dải phân cách đã làm.

2

Một cách khác để giải quyết việc này là sử dụng splitView:shouldAdjustSizeOfSubview:

Tôi đã thấy điều này đơn giản hơn nhiều cho các mục đích của tôi. Ví dụ, nếu bạn muốn ngăn sidebarTableView từ nhỏ hơn chiều rộng tối thiểu 175 thì bạn có thể làm một cái gì đó như thế này (giả sử bạn đã làm sidebarTableXem một lối ra trên bộ điều khiển xem/đại biểu của bạn);

- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview 
{ 
    if ((subview==self.sidebarTableView) && subview.bounds.size.width<=175) { 
     return NO; 
    } 
    return YES; 
} 
3

Vấn đề là khi NSSplitView tự thay đổi kích cỡ, -adjustSubviews được gọi để làm việc, nhưng nó đơn giản bỏ qua/hạn chế tối đa phút từ các đại biểu!

Tuy nhiên -setPosition:ofDividerAtIndex: không tính đến các ràng buộc.

Tất cả bạn cần làm là kết hợp cả hai - ví dụ này giả định một NSSplitView với chỉ 2 lần xem:

- (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 
} 

Điều này dường như làm việc tốt trên OS X 10.8, 10.9 và 10.10, và sạch hơn nhiều so với các cách tiếp cận khác vì nó là mã tối thiểu và các ràng buộc không bị trùng lặp.

0

Có thể đã quá muộn cho bữa tiệc, tuy nhiên đây là việc triển khai của tôi là resizeSubviewWithOldSize:. Trong dự án của tôi, tôi cần một NSplitView có thể thay đổi kích thước theo chiều dọc với chiều rộng leftView từ 100.0 đến 300.0; không có 'Thu gọn' trong tài khoản. Bạn nên chăm sóc tất cả các kích thước có thể cho các bản xem trước.

-(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

ban đầu tôi thực hiện các chức năng NSSplitView đại biểu và kết thúc với rất nhiều mã để cố gắng làm một cái gì đó đơn giản như vậy là giới hạn kích thước tối thiểu cho mỗi bên chia điểm.

Sau đó tôi đã thay đổi cách tiếp cận của mình và tìm thấy giải pháp đơn giản và cực kỳ đơn giản. Tôi chỉ cần đặt hằng số bố cục tự động cho chiều rộng (> = thành kích thước tối thiểu mong muốn) trên NSView cho một bên của NSSplitView. Tôi đã làm như vậy ở phía bên kia của tôi. Với hai ràng buộc đơn giản này, NSSplitView hoạt động hoàn hảo mà không cần các cuộc gọi đại biểu.

0

Tôi đã đạt được hành vi này bằng cách đặt holdingPriority trên NSSplitViewItem thành Bắt buộc (1000) cho mặt cố định trong Trình tạo giao diện. Sau đó, bạn có thể kiểm soát chiều rộng cho mặt cố định bằng cách đặt một ràng buộc trên NSView bên dưới.

0

Tôi chỉ cần thực hiện việc này và đã đưa ra phương pháp này đơn giản hơn các ví dụ trước. Mã này giả định có các IBOutlets cho NSScrollView bên trái và bên phải của thùng chứa NSSplitView, cũng như các hằng số CGFloat cho kích thước tối thiểu của các khung nhìn trái và phải.

#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]; 
    } 
} 
Các vấn đề liên quan