使用Visual AutoLayout在NSScrollView中进行多视图布局 [英] Multiple views layouting in NSScrollView using Visual AutoLayout
问题描述
我需要显示在NSScrollView
内垂直对齐的多个视图,首先添加NSTableView
和NSButton
.我将它们垂直对齐,顶部为NSTableView
,底部为NSButton
.
我将NSTableview
和NSButton
添加到了名为 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屋!