使用Visual AutoLayout在NSScrollView中布局多个视图

时间:2015-04-08 20:19:48

标签: objective-c macos autolayout nsview nsscrollview

我需要在NSScrollView内显示垂直对齐的多个视图,我首先添加了NSTableViewNSButton。我将它们垂直对齐,顶部为NSTableView,底部为NSButton。  我将NSTableviewNSButton添加到名为 tempView NSView中。然后将NSScrollView的文档视图设置为 tempView

但我遇到的问题是我的tableview没有正确扩展我看到按钮没问题,但tablview没有正确扩展,只显示适合表格的最后一个条目。 正如您在下图所示,它显示最后4行20行。 enter image description here] 我的代码如下

-(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 个答案:

答案 0 :(得分:2)

问题似乎是表格视图没有内在高度。因此,它不是&#34;推动&#34;反对文档视图的边界使文档视图变大,因此它会滚动。

我注意到如果我将表视图添加到IB中的窗口然后告诉IB将整个窗口(或剪辑视图或表视图)重置为建议的约束,则表视图和表之间没有添加约束剪辑视图。此外,表格视图仍然启用了translatesAutoresizingMaskIntoConstraints。这与滚动视图中的某些其他类型的视图不同。所以,我认为IB知道表格视图不是自动布局精明的。

我认为直接在剪辑视图中的表视图(如IB设置一个)只是使用旧样式机制来定位和调整自身。当表视图计算其大小(例如,添加了一行)时,它可能只调用-setFrameSize:本身。剪辑视图通过观察NSViewFrameDidChangeNotification通知来监视其帧。这在你的情况下不起作用,因为自动布局基本上忽略/撤消了设置框架的尝试。

可以能够使用它,但它会有点冒险。您将保留表格视图的translatesAutoresizingMaskIntoConstraints,但这会限制您可以设置的约束而不会引起冲突。基本上,您不能设置在表格视图上施加位置或大小的约束,但您可以“挂起”#34;表视图的其他视图,只要它们可以自由移动或调整大小,以便表视图可以自由移动和调整大小。

首先,您的文档视图(tempView)应该是一个翻转视图,因为您希望通过设置其框架然后将表格视图放置在其顶部通过设置框架大小来调整自身大小,并希望它能够长大。

使用非零大小的框架初始化文档视图。起源并不重要。

使用框架初始化表视图,其原点位于(0,0)并且与文档视图的大小相同。别忘了忘记translatesAutoresizingMaskIntoConstraints

不要将表视图的顶部,前导或后缘约束到其超级视图。不要限制其宽度以匹配按钮。我认为,表视图与其superview和按钮之间的其他约束很好。因此,kViewVertical应删除第一个|。你应该完全摆脱kTextViewHorizontalkButtonHorizontal没问题。

将表格视图的autoresizingMask设置为NSViewWidthSizable。由于表格视图以与其超视图边界重合的帧开始,这将使表格视图的左右边缘与超级视图相匹配。 autoresizingMask没有垂直分量。基本上,您不希望更改超级视图的高度以尝试更改表视图的高度。表视图可以自由设置自己的帧高。这将移动按钮,因为它被限制在桌面视图的底部,这将改变文档视图的高度,因为它的底部被限制在按钮的底部。

不要将文档视图(tempView)约束到其底部边缘的剪辑视图。这只是试图强制文档视图的大小是滚动视图的contentSize。这肯定会阻止滚动(通过使滚动视图和窗口增长来显示整个文档视图)。相反,文档视图将改变前一段中讨论的大小,剪辑视图将注意到并相应地更新滚动视图。

我认为,在这一点上,事情将大部分都有效。我怀疑当滚动视图足够大以显示按钮和整个表视图时,它们将被固定到滚动视图的底部而不是顶部,这将更自然。要解决此问题,请使用翻转的NSClipView子类。