【问题标题】:Resize NSView to its subview using auto layout使用自动布局将 NSView 调整为其子视图
【发布时间】:2014-07-06 14:13:27
【问题描述】:

在 Interface Builder 中,我添加了一个 NSScrollView 和一个 NSImageView、一些标签、一个水平分隔符和一个 NSViewNSScrollView 如下所示:

每个元素都有左上角的约束,分隔符和自定义视图也有右上的约束。

有时我需要更改自定义视图的内容。我使用以下代码执行此操作(options 是自定义视图,view 是我要显示的视图):

[view setTranslatesAutoresizingMaskIntoConstraints:NO];
options.subviews = [NSArray arrayWithObject:view];

// Fix the constraints.
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(view);
[options addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:viewsDictionary]];
[options addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:viewsDictionary]];

这在一定程度上是可行的:正确的内容显示在视图中,内容的宽度根据约束改变。但是options 视图的高度并没有改变,所以view 视图的某些内容没有显示出来。我试图通过手动设置框架来改变这一点,但这不起作用。另外,我尝试了以下设置约束:

[options addConstraint:[NSLayoutConstraint constraintWithItem:options attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:view attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];

但没有任何效果。有谁知道我该如何解决这个问题?

我注意到的第二个问题是,即使NSScrollView 的内容大于NSScrollView 本身,滚动也不起作用。不显示滚动条。我该如何解决?

我仍然无法解决这些更难的约束问题...

【问题讨论】:

  • 看起来您的视图有不明确的约束,尝试为宽度和高度设置“默认”值以解决不明确性并使用优先级 (@) 来定义调整大小容差。
  • @JanCássio:“默认”值是什么意思?固定宽度和高度?还是宽度和高度限制?我都试过了,但都不管用......而且,我玩过宽容,但这也不起作用。如果我还在 NSScrollView 上设置约束,就会发生奇怪的事情:NSScrollView 的宽度会根据自定义视图的内容而变化。我做错了什么?

标签: objective-c cocoa autolayout nsview nsscrollview


【解决方案1】:

我设法解决了我的问题。原来我真的有两个问题:

  1. 我没有对 NSScrollView 及其子项设置正确的约束;
  2. 我更改了自定义视图的内容,但没有更改其高度。

我对这两个问题的解决方法如下。


NSScrollView 约束

在Interface Builder中添加一个NSScrollView并在文档视图(剪辑视图的子视图)中放置一些UI元素后,我有以下界面(窗口的白色部分是NSScrollView,不要看约束现在):

如果您运行此程序并调整窗口大小,则不会显示滚动条。首先,我们必须在文档视图上添加相对于其父视图的顶部和前导约束。现在我们需要指定文档视图的大小。这可以通过两种方式完成,具体取决于您的用例:

  1. 为文档视图的宽度和高度添加约束。这样总是显示相同的滚动条。除非您自动更新这些约束,否则文档视图不会根据内容改变大小;
  2. 为文档视图的每个子视图添加约束,以便可以计算文档视图的宽度和高度。这是我的问题所需要的,这些约束显示在上图中。

如果你运行它,一切都会按预期运行。我们仍然无法更改自定义视图的内容,这是另一个问题。


更改自定义视图

现在我们只需要更改自定义视图的内容。由于我们在自定义视图上设置了约束,因此也应该更改这些约束。所有这一切都是通过以下不言自明的代码完成的(自定义视图名为content):

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [content setAutoresizesSubviews:NO];
}

- (IBAction)button1:(id)sender {
    [self showContent:view1];
}

- (IBAction)button2:(id)sender {
    [self showContent:view2];
}

- (void)showContent:(NSView *)c {
    // Remove all constraints.
    [content removeConstraints:content.constraints];

    // Add a height constraint.
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:content attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:c.frame.size.height];
    [content addConstraint:constraint];

    // Add a width constraint.
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:content attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:c.frame.size.width];
    [content addConstraint:constraint];

    [c setTranslatesAutoresizingMaskIntoConstraints:NO];

    // Set the content.
    content.subviews = [NSArray arrayWithObject:c];

    // Add constraints from the content view to its child view.
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(c);
    [content addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[c]|" options:0 metrics:nil views:viewsDictionary]];
    [content addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[c]|" options:0 metrics:nil views:viewsDictionary]];
}

我希望这个答案可以省去其他人发现 NSScrollView 和自动布局的奇怪行为的麻烦。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多