ios 以编程方式添加 CenterX/CenterY 约束
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27624133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Programmatically Add CenterX/CenterY Constraints
提问by Mario A Guzman
I have a UITableViewController that doesn't display any sections if there is nothing to show. I've added a label to indicate to the user that there is nothing to display with this code:
我有一个 UITableViewController,如果没有任何显示,它不会显示任何部分。我添加了一个标签来向用户表明此代码没有可显示的内容:
label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"
self.tableView.addSubview(label)
But now, I want it to be centered Horizontally and Vertically. Normally, I would choose the two options highlighted (plus ones for height and width) in the screenshot:
但是现在,我希望它水平和垂直居中。通常,我会选择屏幕截图中突出显示的两个选项(加上高度和宽度的选项):
I've tried the following code to add the constraints but the app crashes with error:
我尝试了以下代码来添加约束,但应用程序因错误而崩溃:
label = UILabel(frame: CGRectMake(20, 20, 250, 100))
label.text = "Nothing to show"
let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)
label.addConstraint(xConstraint)
label.addConstraint(yConstraint)
error:
错误:
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2014-12-23 08:17:36.755 [982:227877] *** Assertion failure in -[UILabel _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /SourceCache/UIKit/UIKit-3318.16.21/NSLayoutConstraint_UIKitAdditions.m:560
The label should always center horizontally and vertically because the app supports rotation of the device.
标签应始终水平和垂直居中,因为应用程序支持设备旋转。
What am I doing wrong? How do I add these constraints successfully?
我究竟做错了什么?如何成功添加这些约束?
Thanks!
谢谢!
回答by vacawama
Update for Swift 3/Swift 4:
Swift 3/Swift 4 的更新:
As of iOS 8, you can and should activate your constraints by setting their isActive
property to true
. This enables the constraints to add themselves to the proper views. You can activate multiple constraints at once by passing an array containing the constraints to NSLayoutConstraint.activate()
从 iOS 8 开始,您可以并且应该通过将约束的isActive
属性设置为 来激活约束true
。这使约束能够将自己添加到正确的视图中。您可以通过将包含约束的数组传递给一次激活多个约束NSLayoutConstraint.activate()
let label = UILabel(frame: CGRect.zero)
label.text = "Nothing to show"
label.textAlignment = .center
label.backgroundColor = .red // Set background color to see if label is centered
label.translatesAutoresizingMaskIntoConstraints = false
self.tableView.addSubview(label)
let widthConstraint = NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 250)
let heightConstraint = NSLayoutConstraint(item: label, attribute: .height, relatedBy: .equal,
toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 100)
let xConstraint = NSLayoutConstraint(item: label, attribute: .centerX, relatedBy: .equal, toItem: self.tableView, attribute: .centerX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .centerY, relatedBy: .equal, toItem: self.tableView, attribute: .centerY, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([widthConstraint, heightConstraint, xConstraint, yConstraint])
Better Solution:
更好的解决方案:
Since this question was originally answered, layout anchors were introduced making it much easier to create the constraints. In this example I create the constraints and immediately activate them:
由于最初回答了这个问题,因此引入了布局锚点,使创建约束变得更加容易。在这个例子中,我创建了约束并立即激活它们:
label.widthAnchor.constraint(equalToConstant: 250).isActive = true
label.heightAnchor.constraint(equalToConstant: 100).isActive = true
label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor).isActive = true
or the same using NSLayoutConstraint.activate()
:
或相同的使用NSLayoutConstraint.activate()
:
NSLayoutConstraint.activate([
label.widthAnchor.constraint(equalToConstant: 250),
label.heightAnchor.constraint(equalToConstant: 100),
label.centerXAnchor.constraint(equalTo: self.tableView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: self.tableView.centerYAnchor)
])
Note: Always add your subviews to the view hierarchy beforecreating and activating the constraints.
注意:在创建和激活约束之前,始终将您的子视图添加到视图层次结构中。
Original Answer:
原答案:
The constraints make reference to self.tableView
. Since you are adding the label as a subview of self.tableView
, the constraints need to be added to the "common ancestor":
约束参考self.tableView
. 由于您将标签添加为 的子视图self.tableView
,因此需要将约束添加到“共同祖先”:
self.tableView.addConstraint(xConstraint)
self.tableView.addConstraint(yConstraint)
As @mustafa and @kcstricks pointed out in the comments, you need to set label.translatesAutoresizingMaskIntoConstraints
to false
. When you do this, you also need to specify the width
and height
of the label with constraints because the frame no longer is used. Finally, you also should set the textAlignment
to .Center
so that your text is centered in your label.
正如@mustafa 和@kcstricks 在评论中指出的那样,您需要设置 label.translatesAutoresizingMaskIntoConstraints
为false
. 执行此操作时,您还需要指定带有约束的标签的width
和height
,因为不再使用框架。最后,您还应该将 设置textAlignment
为.Center
使您的文本在标签中居中。
var label = UILabel(frame: CGRectZero)
label.text = "Nothing to show"
label.textAlignment = .Center
label.backgroundColor = UIColor.redColor() // Set background color to see if label is centered
label.translatesAutoresizingMaskIntoConstraints = false
self.tableView.addSubview(label)
let widthConstraint = NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 250)
label.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: label, attribute: .Height, relatedBy: .Equal,
toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 100)
label.addConstraint(heightConstraint)
let xConstraint = NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterX, multiplier: 1, constant: 0)
let yConstraint = NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: self.tableView, attribute: .CenterY, multiplier: 1, constant: 0)
self.tableView.addConstraint(xConstraint)
self.tableView.addConstraint(yConstraint)
回答by Suragch
Center in container
容器中的中心
The code below does the same thing as centering in the Interface Builder.
下面的代码与在 Interface Builder 中居中执行相同的操作。
override func viewDidLoad() {
super.viewDidLoad()
// set up the view
let myView = UIView()
myView.backgroundColor = UIColor.blue
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
// Add code for one of the constraint methods below
// ...
}
Method 1: Anchor Style
方法一:锚式
myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Method 2: NSLayoutConstraint Style
方法二:NSLayoutConstraint 样式
NSLayoutConstraint(item: myView, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: myView, attribute: NSLayoutConstraint.Attribute.centerY, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerY, multiplier: 1, constant: 0).isActive = true
Notes
笔记
- Anchor style is the preferred method over
NSLayoutConstraint
Style, however it is only available from iOS 9, so if you are supporting iOS 8 then you should still useNSLayoutConstraint
Style. - You will also need to add length and width constraints.
- My full answer is here.
- Anchor style 是比
NSLayoutConstraint
Style更受欢迎的方法,但是它只在 iOS 9 中可用,所以如果你支持 iOS 8,那么你仍然应该使用NSLayoutConstraint
Style。 - 您还需要添加长度和宽度约束。
- 我的完整答案在这里。
回答by Paul Gee
The ObjectiveC equivalent is:
ObjectiveC 的等价物是:
myView.translatesAutoresizingMaskIntoConstraints = NO;
[[myView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] setActive:YES];
[[myView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] setActive:YES];
回答by YaBoiSandeep
Programmatically you can do it by adding the following constraints.
您可以通过添加以下约束以编程方式实现。
NSLayoutConstraint *constraintHorizontal = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:attribute
multiplier:1.0f
constant:0.0f];
NSLayoutConstraint *constraintVertical = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:attribute
multiplier:1.0f
constant:0.0f];
回答by PiKey
In Swift 5 it looks like this:
在 Swift 5 中,它看起来像这样:
label.translatesAutoresizingMaskIntoConstraints = false
label.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: vc.view.centerYAnchor).isActive = true
回答by coletrain
A solution for me was to create a UILabel
and add it to the UIButton
as a subview. Finally I added a constraint to center it within the button.
我的一个解决方案是创建一个UILabel
并将其UIButton
作为子视图添加到。最后,我添加了一个约束,使其在按钮内居中。
UILabel * myTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 75)];
myTextLabel.text = @"Some Text";
myTextLabel.translatesAutoresizingMaskIntoConstraints = false;
[myButton addSubView:myTextLabel];
// Add Constraints
[[myTextLabel centerYAnchor] constraintEqualToAnchor:myButton.centerYAnchor].active = true;
[[myTextLabel centerXAnchor] constraintEqualToAnchor:myButton.centerXAnchor].active = true;
回答by Adam Kalnas
If you don't care about this question being specifically about a tableview, and you'd just like to center one view on top of another view here's to do it:
如果您不关心这个问题是专门针对 tableview 的,并且您只想将一个视图居中放置在另一个视图之上,请执行以下操作:
let horizontalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
parentView.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: newView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: parentView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
parentView.addConstraint(verticalConstraint)