使用 Visual AutoLayout 在 NSScrollView 中布局多个视图 [英] Multiple views layouting in NSScrollView using Visual AutoLayout

查看:16
本文介绍了使用 Visual AutoLayout 在 NSScrollView 中布局多个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to show multiple views aligned vertically inside NSScrollView, I started by adding NSTableView and NSButton. I aligned them vertically with NSTableView on top and NSButton on bottom. I added NSTableview and NSButton to an NSView called tempView. And then set the document view of NSScrollView to tempView.

但我遇到的问题是我的 tableview 没有正确展开我看到按钮正常但是 tablview 没有正确展开并且只显示适合表格的最后一个条目.正如您在下图中看到的,它显示最后 4 行,共 20 行.]我的代码如下

But problem i am having is my tableview does not expand properly i see the buttons alright but tablview does not expands properly and just show the last entries that fits in the table. As you can see in following image it displays last 4 rows of 20 rows. ] My code is as follow

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

我不明白这种行为的原因.

I am not getting the reason for such behavior.

[_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}.

推荐答案

问题似乎是table view没有固有高度.因此,它不会推动"文档视图的边界以使文档视图变大,因此它会滚动.

The problem seems to be that the table view has no intrinsic height. Therefore, it's not "pushing" against the document view's bounds to make the document view larger, so it scrolls.

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

I notice that if I add a table view to a window in IB and then tell IB to reset the whole window (or the clip view or table view) to suggested constraints, there are no constraints added between the table view and the clip view. Also, the table view still has translatesAutoresizingMaskIntoConstraints enabled. This is different from some other types of views in scroll views. So, I think that IB knows that table views aren't auto layout-savvy.

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

I believe that a table view directly in a clip view (as IB sets one up) just uses the old style mechanism for positioning and sizing itself. When a table view computes its size (e.g. a row is added), it probably just calls -setFrameSize: on itself. The clip view monitors its frame by observing NSViewFrameDidChangeNotification notification. This doesn't work in your case because auto layout basically ignores/undoes attempts to set the frame.

也许可以使用它,但它会很冒险.您可以保留表格视图的 translatesAutoresizingMaskIntoConstraints ,但这会限制您可以设置哪些约束而不会引起冲突.基本上,您不能设置对表格视图施加位置或大小的约束,但是您可以将其他视图从表格视图挂起",只要它们可以自由移动或调整大小,以便表格视图可以自由移动移动和调整大小.

You may be able to work with this, but it will be dicey. You would leave the table view's translatesAutoresizingMaskIntoConstraints on, but that imposes limits on what constraints you can set without causing conflicts. Basically, you can't set constraints that impose a position or size on the table view, but you can "hang" other views off of the table view so long as they are free to move or resize so that the table view is free to move and resize.

首先,您的文档视图 (tempView) 应该是翻转视图,因为您需要通过设置其框架将表格视图定位在其顶部,然后它会自行调整大小通过设置它的帧大小,你希望它变小.

First, your document view (tempView) should be a flipped view, because you're going to want to position the table view at its top by setting its frame and then it's going to resize itself by setting its frame size and you want it to grow down.

使用非零大小的框架初始化文档视图.来源无关紧要.

Init the document view with a frame with non-zero size. The origin doesn't matter.

使用原点位于 (0, 0) 且与文档视图大小相同的框架初始化表格视图.不要忘记打开它的 translatesAutoresizingMaskIntoConstraints.

Init the table view with a frame whose origin is at (0, 0) and with the same size as the document view. Don't forget to leave its translatesAutoresizingMaskIntoConstraints on.

不要将表格视图的顶部、前导或后沿限制为其父视图.不要限制其宽度以匹配按钮.我认为,表视图与其父视图和按钮之间的其他约束都很好.因此,kViewVertical 应该删除第一个 |.您应该完全摆脱 kTextViewHorizo​​ntal .kButtonHorizo​​ntal 很好.

Do not constrain the top, leading, or trailing edges of the table view to its superview. Don't constrain its width to match the button. The other constraints between the table view and its superview and button are fine, I think. So, kViewVertical should drop the first |. You should get rid of kTextViewHorizontal entirely. kButtonHorizontal is fine.

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

Set the table view's autoresizingMask to NSViewWidthSizable. Since the table view started with a frame coincident with its superview's bounds, that will keep the table view's left and right edges matching the superview's. There is no vertical component of the autoresizingMask. Basically, you don't want changes in the height of the superview to try to change the height of the table view. The table view is free to set its own frame height. That will move the button, because it's constrained to the table view's bottom, and that will change the height of the document view, because its bottom is constrained to the button's bottom.

不要将文档视图 (tempView) 限制在其底部边缘的剪辑视图中.这只是试图强制文档视图成为滚动视图的 contentSize 的大小.这肯定会阻止滚动(通过使滚动视图和窗口增长以显示整个文档视图).相反,文档视图将改变大小,如前一段所述,剪辑视图会注意到这一点并相应地更新滚动视图.

Do not constrain the document view (tempView) to the clip view on its bottom edge. That just tries to force the document view to be the size of the contentSize of the scroll view. That is sure to prevent scrolling (by making the scroll view and the window grow to show the entire document view). Rather, the document view will change size as discussed in the previous paragraph and the clip view will notice that and update the scroll view accordingly.

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

I think that at this point, things will mostly work. I suspect that when the scroll view is large enough to show both the button and the whole table view, they will be pinned to the bottom of the scroll view rather than the top which would be more natural. To fix that, use a subclass of NSClipView that is flipped.

这篇关于使用 Visual AutoLayout 在 NSScrollView 中布局多个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆