我有一个窗口,其中包含一个自定义视图,我希望自定义视图可以随窗口调整大小,以便随时完全填充它。 如果我写:
NSView *contentView = [self.window contentView];
CustomView *customView = [[CustomView alloc] initWithFrame:[contentView bounds]];
[contentView addSubview:customView];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
然后窗口不让我调整大小。
如果我添加:
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
然后不显示自定义视图(似乎永远不会调用drawRect:
)。
我尝试了不同的方式(包括视觉格式@"|[customview]|"
),但我总是遇到同样的问题。我知道可以使用旧的自动调整系统来完成:
[customView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
但是我想使用Cocoa Auto Layout系统,我想将它用于更复杂的情况(比如总是填满窗口的几个自定义视图)。
有谁知道什么是错的,我应该如何使用自动布局系统来获得我想要的结果?
答案 0 :(得分:107)
使用自动布局,有(至少)三种可能的方式来约束视图,使其占据整个窗口的内容视图,并在适当时调整大小。
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
NSDictionary *views = NSDictionaryOfVariableBindings(customView);
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|"
options:0
metrics:nil
views:views]];
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|"
options:0
metrics:nil
views:views]];
(这应该等同于上面的可视格式)
+ (void)addEdgeConstraint:(NSLayoutAttribute)edge superview:(NSView *)superview subview:(NSView *)subview {
[superview addConstraint:[NSLayoutConstraint constraintWithItem:subview
attribute:edge
relatedBy:NSLayoutRelationEqual
toItem:superview
attribute:edge
multiplier:1
constant:0]];
}
和
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeLeft superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeRight superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeTop superview:contentView subview:customView];
[[self class] addEdgeConstraint:NSLayoutAttributeBottom superview:contentView subview:customView];
NSView *contentView = [_window contentView];
MyView *customView = [[MyView alloc] initWithFrame:[contentView bounds]];
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:customView];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
[contentView addConstraint:
[NSLayoutConstraint constraintWithItem:customView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:contentView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
第三种方法是问题中列出的方法,如果存在进一步的限制,它可能无效。例如,没有:
[customView setTranslatesAutoresizingMaskIntoConstraints:NO];
也会应用原始自动调整大小的掩码,这会导致问题中描述的行为:窗口未调整大小。
如Regexident所述,您可以使用:
[_window visualizeConstraints:[contentView constraints]];
调试自动布局。值得检查控制台输出。
答案 1 :(得分:47)
@ Bavarious的答案很好,我只想补充几点。
学习使用内置的调试支持非常重要!正如许多发展一样,希望你在第一次拍摄时始终能够做到一切都是不现实的。这是自动布局的一个主要问题,因此我们花了很多精力进行调试。步骤,简要说明:
通常你发布的问题(我的东西不起作用!)不足以让人们知道什么是错的,这是使用调试内容的重要原因之一。有关详细信息,请参阅WWDC 2011会话视频(全民免费)和文档。
Buuuuut我实际上可以告诉这次出了什么问题。 :-)在关闭translatesAutoresizingMaskIntoConstraints之前,你比你想要的更受约束 - 视图的宽度和高度也是固定的,这就是窗口无法调整大小的原因。你把它关掉后,你的布局模糊不清,因为你没有把视线固定在任何东西上!你曾经说过它应该有多大(和superview一样),但不是它应该是。
肯
Cocoa Frameworks,主要自动布局作者
答案 2 :(得分:6)
您可以使用非常容易阅读的格式创建布局锚点约束:
Swift2代码
func fit(childView: UIView, parentView: UIView) {
childView.translatesAutoresizingMaskIntoConstraints = false
childView.topAnchor.constraintEqualToAnchor(parentView.topAnchor).active = true
childView.leadingAnchor.constraintEqualToAnchor(parentView.leadingAnchor).active = true
childView.trailingAnchor.constraintEqualToAnchor(parentView.trailingAnchor).active = true
childView.bottomAnchor.constraintEqualToAnchor(parentView.bottomAnchor).active = true
}
使用:
parrentView.addSubview(childView)
fit(childView, parentView: parrentView)
答案 3 :(得分:0)
我发现-drawRect:在框架矩形为0,0,0,0的情况下不会被调用。不受欢迎的约束似乎导致框架变为0,0,0,0。