我正在尝试使用可视化格式语言来集中视图。
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView(300)]-|" options:NSLayoutFormatAlignAllCenterY metrics:0 views:views]];
(views
是NSDictionaryOfVariableBindings
,其中包含_progressView
)
它不会将我的视图(宽度:300)置于self.view
(宽度:768)内。它将左边的边距与8像素边距对齐,好像我只写了@"H:|-[_progressView(300)"
。
是使用以下内容实现视图居中的唯一方法吗?
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_progressView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
由于
答案 0 :(得分:34)
此格式字符串
@"H:|-[_progressView(300)]-|"
不会告诉AutoLayout居中progressView
。相反,它表示progressView
应该是300宽,并且在超视图边缘的任一侧都有一个系统定义的标准边距。显然这不能满足,因此Auto Layout会删除一些约束(您可能会在控制台上获得一些日志)。在你的案例中删除的约束可能是右边的边距。
要真正将视图置于其超级视图中心,您必须使用详细约束方法而不是可视字符串格式,正如您已经想到的那样。但是,你可以很容易地把它放到这样一个很好的类别中:
@interface UIView (MyLayout)
- (void)centerHorizontallyInSuperview;
@end
@implementation UIView (MyLayout)
- (void)centerHorizontallyInSuperview {
NSLayoutConstraint *c;
c = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0];
[self.superview addConstraint:c];
}
@end
答案 1 :(得分:17)
三种方法:
您可以根据DrummerB的建议将约束添加到方法或类别中。
你也是有效的iOS 9,可以使用更新,更简洁的语法,使用锚点并使用activateConstraints
:
[NSLayoutConstraint activateConstraints:@[
[centerView.centerXAnchor constraintEqualToAnchor:view.centerXAnchor],
...
]];
或者在Swift 3中:
NSLayoutConstraint.activate([
centerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
...
])
您可以使用UILayoutGuide
个对象:
UILayoutGuide *leftGuide = [[UILayoutGuide alloc] init];
[view addLayoutGuide:leftGuide];
UILayoutGuide *rightGuide = [[UILayoutGuide alloc] init];
[view addLayoutGuide:rightGuide];
并用VFL将它们定义为彼此相等:
H:|[leftGuide][_progressView(==300)][rightGuide(==leftGuide)]|
如果你不能使用布局指南(例如你需要支持9.0之前的iOS版本,你想在IB中创建它等)你可以使用不可见的UIView
对象(alpha为零)或以非常相似的方式的背景颜色。只需将这些“spacer”视图添加到视图层次结构中,使用上面的水平约束,但只需配置视图就可以看不到它们。
这种技术是一种解决“视图中心”问题的麻烦方法,但如果您想要均匀地分隔十几个视图并且不能使用{{1 }} 由于某些原因。您可以使用所需的UIStackView
个(或不可见的UILayoutGuide
)个对象来实现所需的效果。
为了完整起见,我应该指出,如https://stackoverflow.com/a/14917695/1271826中所述,使用UIView
/ options
的{{1}}可以达到效果。但我承认我发现它不必要地混淆了。
就个人而言,我认为第一种方法对您的场景最有意义。第二种方法在尝试均匀分布一堆控件时很有用,但对于这种简单的场景来说太笨拙了。第三种方法是求知欲,但我不会在任何实际应用中提出建议。
答案 2 :(得分:7)
对于那些需要它的人,@ DrummerB的ObjC类别作为Swift扩展:
extension UIView {
func centerInSuperview() {
self.centerHorizontallyInSuperview()
self.centerVerticallyInSuperview()
}
func centerHorizontallyInSuperview(){
let c: NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, toItem: self.superview, attribute: .CenterX, multiplier: 1, constant: 0)
self.superview?.addConstraint(c)
}
func centerVerticallyInSuperview(){
let c: NSLayoutConstraint = NSLayoutConstraint(item: self, attribute: .CenterY, relatedBy: .Equal, toItem: self.superview, attribute: .CenterY, multiplier: 1, constant: 0)
self.superview?.addConstraint(c)
}
}