OS X自动布局防止窗口调整大小。

4

针对自动布局专家的问题:我不明白为什么以下自动布局设置会防止窗口调整大小。

我有三个视图按照以下方式组织:

-----------------
|           |   |
|     F     | S |
|           |   |
-----------------
|     B     |
-------------

S具有固定的宽度,B具有固定的高度,而F应始终具有S的高度和B的宽度。以下是我设置的约束条件:

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[F(>=100)][S(==100)]|"
                                                             options:0
                                                             metrics:nil
                                                               views:@{ @"F": _f, @"S": _s }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[F(>=100)][B(==100)]|"
                                                             options:0
                                                             metrics:nil
                                                               views:@{ @"F": _f, @"B": _b }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[B(==F)]"
                                                             options:0
                                                             metrics:nil
                                                               views:@{ @"B": _b, @"F": _f }]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[S(==F)]"
                                                             options:0
                                                             metrics:nil
                                                               views:@{ @"S": _s, @"F": _f }]];

我认为,这应该允许我自由调整窗口大小,使用 F 键可以填充空间。但是,约束条件完全锁定了窗口的大小调整。
有什么想法吗?我在哪里出错了?
谢谢。
2个回答

2
我曾多次遇到这个基本问题,因为视图中的translatesAutoresizingMaskIntoConstraints属性被设置为YES。
这个属性过去可以通过Xcode UI编辑器中的复选框来控制,但在Xcode 6.1.1中,该复选框已经消失。然而,对于在代码中创建的视图(例如WKWebView,它不支持从.xib文件实例化),或者对于使用早期版本的Xcode创建的视图,此属性可能被设置为YES。
如果是这样,那么自动布局会以意想不到的方式运作,通常包括您无法调整窗口大小的症状。您手动配置了视图随窗口一起调整大小,但自动调整大小掩码的转换可能会添加额外的约束,如果窗口增大,则无法同时满足这些约束。
为了说明问题,请考虑下面的方法。这扩展了NSView以添加一个方法,该方法将另一个视图调整为接收者的大小,将其作为接收者的子视图添加,并设置自动布局约束,以使子视图随其父视图(接收者)一起增长和缩小。
然而,我们注意到这里有一个错误,通常情况下它工作得很好,但有时包含所有视图的窗口将变得不可调整大小。原因是在某些情况下subview.translatesAutoresizingMaskIntoConstraints为YES,这会导致不需要的额外布局约束阻止窗口调整大小。添加倒数第二行修复了该错误。
这可能是您的情况(取决于您的视图是如何创建的)。
@implementation NSView (Nakahara)

- (void)nakahara_embedSubview:(NSView *)subview;
{
    subview.frame = self.bounds;
    [self addSubview:subview];

    NSArray *newConstraints =
    @[
      [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0],
      [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0],
      [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0],
      [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0],
      ];

    subview.translatesAutoresizingMaskIntoConstraints = NO;
      // IMPORTANT! It took a while to figure out why this was sometimes working and sometimes not. It was because subview.translatesAutoresizingMaskIntoConstraints is sometimes YES and sometimes NO, and if it is YES, autolayout will break in undefined ways (e.g., windows suddenly become unresizable).

    [self addConstraints:newConstraints];
}


@end

1
当您创建新的约束时,默认优先级为1000(NSLayoutPriorityRequired)。这意味着自动布局引擎可能会影响窗口大小以满足您的约束。
如果您将约束的优先级设置为小于500(NSLayoutPriorityWindowSizeStayPut),则应获得所需的行为。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接