Ответ 1
Что вы ищете:
- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
[sender frame]
будет новый размер вашего NSSplitView
после изменения размера. Затем просто отрегулируйте свои подвид. Соответственно.
У меня есть 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 пикселями, и это отлично работает при использовании разделителя. Но при изменении размера всего окна делитель вытесняется из этих ограничений.
Кто-нибудь знает, как это контролировать?
Дополнительно: если я хочу сохранить пользовательский выбор ширины боковой панели, хорошо подумать, чтобы прочитать его, сохранить в файл настроек и восстановить его позже, или есть более прямой способ сделать это? Я заметил, что состояние окна сохраняется в некоторых случаях - обычно ли это происходит или мне нужно его контролировать?
Заранее спасибо
Арне
Что вы ищете:
- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
[sender frame]
будет новый размер вашего NSSplitView
после изменения размера. Затем просто отрегулируйте свои подвид. Соответственно.
Проблема заключается в том, что при изменении размера NSSplitView -adjustSubviews
получает вызов для выполнения работы, но он просто игнорирует ограничения min/max из делегата!
Однако -setPosition:ofDividerAtIndex:
учитывает ограничения.
Все, что вам нужно сделать, это объединить оба - этот пример предполагает NSSplitView с двумя видами:
- (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 и намного чище, чем другие подходы, поскольку это минимальный код, а ограничения не дублируются.
Я изначально реализовал функции делегата NSSplitView
и получил много кода, чтобы попытаться сделать что-то настолько простое, как ограничение минимального размера для каждой из разделенных сторон вида.
Затем я изменил свой подход и нашел чистое и чрезвычайно простое решение. Я просто установил константу автоматического макета для ширины ( >= для моего желаемого минимального размера) на NSView
для одной стороны NSSplitView
. Я сделал то же самое с другой стороны. С этими двумя простыми ограничениями NSSplitView
работал отлично, без необходимости делегирования вызовов.
Альтернативный способ решения этой проблемы - использовать 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;
}
Здесь моя реализация -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
не имеет минимума или максимума и не сжимается.
Я использовал
- (void)splitView:(NSSplitView*)sender resizeSubviewsWithOldSize:(NSSize)oldSize
но вместо изменения рамки subview я использовал
[sender setPosition:360 ofDividerAtIndex:0]; //or whatever your index and position should be
Изменение рамки не дало мне последовательных результатов. Настройка положения разделителя.
Возможно, слишком поздно для вечеринки, однако это моя реализация resizeSubviewWithOldSize:
. В моем проекте мне нужен вертикальный масштабируемый NSplitView с шириной leftView между 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);
}
}
Я достиг такого поведения, установив holdingPriority
на NSSplitViewItem
в Required (1000) для фиксированной стороны в Interface Builder. Затем вы можете контролировать ширину для фиксированной стороны, установив ограничение на базовый NSView
.
Мне просто нужно было это сделать, и придумал этот метод, который немного проще предыдущих примеров. Этот код предполагает, что существуют IBOutlets для левого и правого NSScrollViews контейнера NSSplitView, а также константы CGFloat для минимального размера левого и правого представлений.
#pragma mark - NSSplitView sizing override
//------------------------------------------------------------------------------
// This is implemented to ensure that when the window is resized that our main table
// remains at it 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 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];
}
}