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

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

问题描述

我需要显示在NSScrollView内垂直对齐的多个视图,首先添加NSTableViewNSButton.我将它们垂直对齐,顶部为NSTableView,底部为NSButton. 我将NSTableviewNSButton添加到了名为 tempView NSView中.然后将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不能正确展开,只是显示了适合该表的最后一个条目. 正如您在下图中看到的,它显示20行中的最后4行. ] 我的代码如下

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

推荐答案

问题似乎是表格视图没有固有高度.因此,它不是推动"文档视图的边界以使文档视图更大,因此可以滚动.

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应该删除第一个|.您应该完全摆脱kTextViewHorizontal. kButtonHorizontal很好.

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天全站免登陆