2

我正在尝试使用NSLayoutConstraints 设置视图的布局。

我可以在视图中正确设置内容,但如果约束需要,我还需要能够调整当前视图(我为其设置约束的视图)的大小。换句话说,我想用一个灵活的窗口设置一个固定的内容大小,而不是相反。

所以基本上,我有:

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扩展(或收缩)以适应更改的高度。

我不确定它是否相关(因为我对 iOS 比对 OS X 更熟悉),但这是NSPopover.

我需要添加什么约束来实现这一点?

4

4 回答 4

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“通过删除它,重新创建它,然后阅读它”。这是不必要的,也不推荐。该constant属性是可修改的。正如文档所说

    “与其他属性不同,constant可以在创建约束后对其进行修改。constant在现有约束上设置 比删除约束并添加一个与旧约束一样但具有新约束的新约束要好得多constant。”

    因此,这意味着您可以执行以下简单的操作:

    self.v1Height.constant = newHeight;
    [UIView animateWithDuration:0.5
                     animations:^{
                         [self layoutIfNeeded];
                     }];
    
于 2013-06-16T15:58:06.213 回答
4

事实证明,这NSPopoverController是规则的一个例外,并且translatesAutoresizingMaskIntoConstraints必须是YES自动布局才能正常工作。

于 2013-06-16T22:47:55.427 回答
2

迟到总比没有好...

对于 Storyboard、IB 和 Swift:

只需像任何其他控件一样将您的约束控制拖动到您的 viewController

@IBOutlet weak var spaceToTopThatIDecided: NSLayoutConstraint!

然后简单地改变它:

spaceToTopThatIDecided.constant = 44

就这样!

于 2014-10-22T19:31:18.053 回答
0

我找到了一个简单的解决方案来使用类别更新约束(调整大小):

隐藏自动布局 UIView:如何让现有的 NSLayoutConstraint 更新这个

于 2014-03-13T17:34:11.803 回答