我正在尝试使用NSLayoutConstraint
s设置视图的布局。
我可以在视图中正确设置,但是如果约束需要,我还需要能够调整当前视图(我正在设置约束的视图)。换句话说,我想用灵活的窗口设置固定的内容大小,而不是反过来。
基本上,我有:
NSDictionary *views = [NSDictionary dictionaryWithObjectsAndKeys:self.v1, @"v1",
self.v2, @"v2",
nil];
// Set horizontal constraints
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[v1]-|"
options:0
metrics:nil
views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[v2]-|"
options:0
metrics:nil
views:views]];
// Set vertical constraints
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[v1]-[v2]-|"
options:0
metrics:nil
views:views]];
// Initialise height constraint for v1
self.v1Height = [NSLayoutConstraint constraintWithItem:self.v1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50];
如果我稍后更改self.v1Height
(通过删除它,重新创建它,然后重新读取它),我希望self
的框架扩展(或收缩)以适应更改的高度。< / p>
我不确定它是否相关(因为我比iOS更熟悉iOS),但这是NSPopover
的内容视图。
为实现这一目标,我需要添加什么约束?
答案 0 :(得分:7)
有几个问题:
如果您希望约束定义其包含视图的大小,则它们可能不像现在那样模糊不清。他们必须完全定义他们需要的空间。例如:
NSDictionary *views = @{@"v1" : self.v1,
@"v2" : self.v2};
// Set horizontal constraints
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[v1(200)]-|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[v2(==v1)]-|" options:0 metrics:nil views:views]];
// Set vertical constraints
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[v1]-[v2(600)]-|" options:0 metrics:nil views:views]];
// Initialise height constraint for v1
self.v1Height = [NSLayoutConstraint constraintWithItem:self.v1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50];
[self addConstraint:self.v1Height];
注意,我设置v1
的宽度,我设置v2
的宽度与v1
的宽度相同,我设置的是v2
的高度也是。这与您随后创建的v1Height
约束相结合,现在可以使视图的布局明确无误。
完成此操作后,您还需要告诉视图控制器在应用自动布局时通知弹出控制器其内容大小。因此,您的视图控制器可以实现viewDidLayoutSubviews
:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.view.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height);
self.contentSizeForViewInPopover = self.view.frame.size;
}
请注意,frame
的设置非常好奇,但如果您不将原点重置为{0.0, 0.0}
,您的控件就不会出现在正确的位置。你不得不这样做似乎是对的,但根据我的经验,你做到了。
与您的问题有点无关,您提到您要删除v1Height
&#34;删除它,重新创建它,然后再读取它#34;。这是不必要的,不推荐。 constant
属性是可修改的。作为docs say
&#34;与其他属性不同,
constant
可在约束创建后修改。在现有约束上设置constant
比删除约束并添加一个新的约束更好,但是有一个新约constant
。&#34;
因此,这意味着你可以做一些简单的事情:
self.v1Height.constant = newHeight;
[UIView animateWithDuration:0.5
animations:^{
[self layoutIfNeeded];
}];
答案 1 :(得分:4)
事实证明,NSPopoverController
是规则的例外情况,translatesAutoresizingMaskIntoConstraints
必须为YES
才能使自动布局正常工作。
答案 2 :(得分:2)
晚于永远......
对于Storyboard,IB和Swift:
只需控制 - 将约束像任何其他控件一样拖到viewController
@IBOutlet weak var spaceToTopThatIDecided: NSLayoutConstraint!
然后简单地改变它:
spaceToTopThatIDecided.constant = 44
这就是全部!
答案 3 :(得分:0)
我找到了一个简单的解决方案,用类别更新约束(调整大小):
Hide autolayout UIView : How to get existing NSLayoutConstraint to update this one