Расположение нескольких представлений в NSScrollView с использованием Visual AutoLayout

Мне нужно показать несколько видов, выровненных по вертикали внутри NSScrollViewЯ начал с добавления NSTableView а также NSButton, Я выровнял их по вертикали NSTableView сверху и NSButton внизу я добавил NSTableview а также NSButton для NSView называется tempView. А затем установите вид документа NSScrollView для tempView.

Но у меня проблема в том, что мое табличное представление не расширяется должным образом, я вижу кнопки в порядке, но tablview не раскрывается должным образом и просто показывает последние записи, которые помещаются в таблицу. Как вы можете видеть на следующем рисунке, он отображает последние 4 строки по 20 строк.] Мой код следующий

-(void)setupView {
    _scrollView = [[NSScrollView alloc] init];
    [_scrollView setHasVerticalScroller:YES];
    [_scrollView setHasVerticalRuler:YES];
    [_scrollView setBorderType:NSBezelBorder];
    [_scrollView setBackgroundColor:[NSColor purpleColor]];
         _scrollView.autoresizingMask = NSViewHeightSizable;

    _tableView = [[NSTableView alloc] init];
    [_tableView setDataSource:self];
    [_tableView setHeaderView:nil];
    [_tableView addTableColumn:[[NSTableColumn alloc] initWithIdentifier:@"firstColumn"]];
    [_tableView setDelegate:self];
    [_tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
    [_tableView setBackgroundColor:[NSColor greenColor]];

    NSButton* _button = [[NSButton alloc] initWithFrame:NSZeroRect];
    NSView* tempView = [[NSView alloc] initWithFrame:NSZeroRect];

    [tempView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_button setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_tableView setTranslatesAutoresizingMaskIntoConstraints:NO];

    [tempView addSubview:_button];
    [tempView addSubview:_tableView];

    [_scrollView setDocumentView:tempView];
    [self addSubview:_scrollView];


    NSString *const kViewContainerVertical = @"V:|[tempView]|";
    NSString *const kViewContainerHorizontal = @"H:|[tempView]|";

    NSDictionary *viewDictionary = NSDictionaryOfVariableBindings(tempView);

    NSArray *contraintOneView = [NSLayoutConstraint constraintsWithVisualFormat:kViewContainerVertical
                                                                        options:NSLayoutFormatAlignAllLeft
                                                                        metrics:nil
                                                                          views:viewDictionary];

    NSArray *constraintTwoView = [NSLayoutConstraint constraintsWithVisualFormat:kViewContainerHorizontal
                                                                         options:NSLayoutFormatAlignAllLeft
                                                                         metrics:nil
                                                                           views:viewDictionary];


    NSString *const kViewVertical = @"V:|[_tableView]-2-[_button]|";
    NSString *const kTextViewHorizontal = @"H:|[_tableView(_button)]-0-|";
    NSString *const kButtonHorizontal = @"H:|-0-[_button]-0-|";

    NSDictionary *dictionary = NSDictionaryOfVariableBindings(_tableView, _button);

    NSArray *contraintOne = [NSLayoutConstraint constraintsWithVisualFormat:kViewVertical
                                                                    options:NSLayoutFormatAlignAllLeft
                                                                    metrics:nil
                                                                      views:dictionary];

    NSArray *constraintTwo = [NSLayoutConstraint constraintsWithVisualFormat:kTextViewHorizontal
                                                                     options:NSLayoutFormatAlignAllLeft
                                                                     metrics:nil
                                                                       views:dictionary];

    NSArray *constraintThree = [NSLayoutConstraint constraintsWithVisualFormat:kButtonHorizontal
                                                                       options:NSLayoutFormatAlignAllLeft
                                                                       metrics:nil
                                                                         views:dictionary];
    [tempView addConstraints:contraintOne];
    [tempView addConstraints:constraintTwo];
    [tempView addConstraints:constraintThree];

    [_scrollView.contentView addConstraints:contraintOneView];
    [_scrollView.contentView addConstraints:constraintTwoView];


    NSString *const kScrollVertical = @"V:|-0-[_scrollView]-0-|";
    NSString *const kScrollHorizontal = @"H:|-0-[_scrollView]-0-|";

        NSDictionary *scrollDictionary = NSDictionaryOfVariableBindings(_scrollView);

    NSArray *contraintOneScroll = [NSLayoutConstraint constraintsWithVisualFormat:kScrollVertical
                                                                    options:NSLayoutFormatAlignAllLeft
                                                                    metrics:nil
                                                                      views:scrollDictionary];

    NSArray *constraintTwoScroll = [NSLayoutConstraint constraintsWithVisualFormat:kScrollHorizontal
                                                                     options:NSLayoutFormatAlignAllLeft
                                                                     metrics:nil
                                                                       views:scrollDictionary];

    [self addConstraints:contraintOneScroll];
    [self addConstraints:constraintTwoScroll];
}

Я не понимаю причину такого поведения.

[_tableView constraintsAffectingLayoutForOrientation:NSLayoutConstraintOrientationVertical]

Возвращает

<__NSArrayI 0x608000101050>(
<NSContentSizeLayoutConstraint:0x6080000a2520 V:[NSButton:0x608000140c60'Button'(21)] Hug:250 CompressionResistance:750>,
<NSLayoutConstraint:0x608000082620 V:[NSButton:0x608000140c60'Button']-(0)-|   (Names: '|':NSView:0x608000121180 )>,
<NSLayoutConstraint:0x6080000825d0 V:[NSTableView:0x1004032f0]-(2)-[NSButton:0x608000140c60'Button']>,
<NSLayoutConstraint:0x608000082da0 V:|-(0)-[JSFlippedView:0x608000160cc0]   (Names: '|':NSView:0x610000120140 )>,
<NSAutoresizingMaskLayoutConstraint:0x608000081770 h=-&- v=-&- V:|-(1)-[NSClipView:0x100408c20]   (Names: '|':NSScrollView:0x6080001c0000 )>,
<NSLayoutConstraint:0x608000082490 V:[NSView:0x608000121180]-(0)-|   (Names: '|':NSClipView:0x100408c20 )>,
<NSLayoutConstraint:0x6080000828a0 V:[NSScrollView:0x6080001c0000]-(0)-|   (Names: '|':JSFlippedView:0x608000160cc0 )>,
<NSAutoresizingMaskLayoutConstraint:0x608000082fd0 h=-&- v=-&- V:[NSView:0x610000120140]-(0)-|   (Names: '|':NSThemeFrame:0x100403e30'ScrollTest-expand' )>,
<NSLayoutConstraint:0x608000082df0 V:[JSFlippedView:0x608000160cc0]-(0)-|   (Names: '|':NSView:0x610000120140 )>,
<NSLayoutConstraint:0x608000082440 V:|-(0)-[NSView:0x608000121180]   (Names: '|':NSClipView:0x100408c20 )>,
<NSAutoresizingMaskLayoutConstraint:0x608000081540 h=-&- v=-&- V:[NSClipView:0x100408c20]-(1)-|   (Names: '|':NSScrollView:0x6080001c0000 )>,
<NSLayoutConstraint:0x608000082850 V:|-(0)-[NSScrollView:0x6080001c0000]   (Names: '|':JSFlippedView:0x608000160cc0 )>,
<NSAutoresizingMaskLayoutConstraint:0x608000083200 h=-&- v=-&- V:|-(22)-[NSView:0x610000120140]   (Names: '|':NSThemeFrame:0x100403e30'ScrollTest-expand' )>,
<NSLayoutConstraint:0x608000082580 V:|-(0)-[NSTableView:0x1004032f0]   (Names: '|':NSView:0x608000121180 )>,
<NSLayoutConstraint:0x6000000806e0 'NSWindow-current-height' V:[NSThemeFrame:0x100403e30'ScrollTest-expand'(727@500)] priority:500>
)

а также _tableView intrinsicContentSize дает {-1, -1},

1 ответ

Решение

Кажется, проблема в том, что табличное представление не имеет внутренней высоты. Следовательно, это не "толкает" границы документа, чтобы увеличить его, поэтому он прокручивается.

Я замечаю, что если я добавлю табличное представление к окну в IB, а затем скажу IB сбросить все окно (или представление клипа или представление таблицы) в соответствии с предлагаемыми ограничениями, между представлением таблицы и представлением клипа не будет никаких ограничений. Кроме того, табличное представление все еще имеет translatesAutoresizingMaskIntoConstraints включен. Это отличается от некоторых других типов представлений в представлениях прокрутки. Итак, я думаю, что IB знает, что табличные представления не являются автоматически разбирающимися в макете.

Я полагаю, что табличное представление непосредственно в виде клипа (так как IB устанавливает его) просто использует механизм старого стиля для позиционирования и определения размера. Когда табличное представление вычисляет его размер (например, добавляется строка), оно, вероятно, просто вызывает -setFrameSize: на себя. Просмотр клипа контролирует его кадр, наблюдая NSViewFrameDidChangeNotification уведомление. Это не работает в вашем случае, потому что автоматическое расположение в основном игнорирует / отменяет попытки установить фрейм.

Вы можете работать с этим, но это будет рискованно. Вы бы покинули вид таблицы translatesAutoresizingMaskIntoConstraints на, но это накладывает ограничения на то, какие ограничения вы можете установить, не вызывая конфликтов. По сути, вы не можете установить ограничения, которые налагают позицию или размер на табличное представление, но вы можете "повесить" другие представления за пределы табличного представления, если они могут свободно перемещаться или изменять размеры, чтобы табличное представление могло свободно переместить и изменить размер.

Во-первых, ваш документ просмотра (tempView) должно быть перевернутым представлением, потому что вы захотите расположить табличное представление на его вершине, установив его фрейм, а затем оно будет изменять свой размер, устанавливая размер фрейма, и вы хотите, чтобы оно уменьшалось.

Инициируйте представление документа с рамкой с ненулевым размером. Происхождение не имеет значения.

Инициируйте табличное представление с рамкой, источник которой равен (0, 0) и имеет тот же размер, что и представление документа. Не забудьте оставить свой translatesAutoresizingMaskIntoConstraints на.

Не ограничивайте верхнюю, переднюю или заднюю кромки табличного представления его суперпредставлением. Не ограничивайте его ширину, чтобы соответствовать кнопке. Я думаю, что другие ограничения между табличным представлением и его суперпредставлением и кнопкой в ​​порядке. Так, kViewVertical должен бросить первый |, Вы должны избавиться от kTextViewHorizontal полностью. kButtonHorizontal Это хорошо.

Установить вид таблицы autoresizingMask в NSViewWidthSizable, Так как табличное представление началось с фрейма, совпадающего с границами его суперпредставления, это сохранит левый и правый края табличного представления, совпадающие с суперпредставлением. Там нет вертикальной составляющей autoresizingMask, По сути, вы не хотите, чтобы изменения высоты суперпредставления пытались изменить высоту табличного представления. В табличном представлении можно установить собственную высоту кадра. Это переместит кнопку, потому что она ограничена основанием табличного представления, и это изменит высоту представления документа, потому что ее основание ограничено основанием кнопки.

Не ограничивайте вид документа (tempView) к виду клипа по его нижнему краю. Это просто пытается заставить вид документа быть размером contentSize вида прокрутки. Это обязательно предотвратит прокрутку (сделав вид прокрутки и окно увеличенным, чтобы показать весь вид документа). Скорее, представление документа изменит размер, как обсуждалось в предыдущем абзаце, и представление клипа заметит это и обновит представление прокрутки соответствующим образом.

Я думаю, что на данный момент все будет в основном работать. Я подозреваю, что когда представление прокрутки достаточно велико, чтобы отображать как кнопку, так и представление всей таблицы, они будут прикреплены к нижней части представления прокрутки, а не к вершине, которая была бы более естественной. Чтобы исправить это, используйте подкласс NSClipView это перевернуто.

Другие вопросы по тегам