使用NSLayoutConstraints调整当前视图的大小

时间:2013-06-16 04:14:20

标签: objective-c cocoa autolayout nslayoutconstraint

我正在尝试使用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的内容视图。

为实现这一目标,我需要添加什么约束?

4 个答案:

答案 0 :(得分:7)

有几个问题:

  1. 如果您希望约束定义其包含视图的大小,则它们可能不像现在那样模糊不清。他们必须完全定义他们需要的空间。例如:

    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约束相结合,现在可以使视图的布局明确无误。

  2. 完成此操作后,您还需要告诉视图控制器在应用自动布局时通知弹出控制器其内容大小。因此,您的视图控制器可以实现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},您的控件就不会出现在正确的位置。你不得不这样做似乎是对的,但根据我的经验,你做到了。

  3. 与您的问题有点无关,您提到您要删除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