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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:06:36  来源:igfitidea点击:

Programmatically Add CenterX/CenterY Constraints

iosxcodeswiftautolayoutnslayoutconstraint

提问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:

但是现在,我希望它水平和垂直居中。通常,我会选择屏幕截图中突出显示的两个选项(加上高度和宽度的选项):

enter image description here

在此处输入图片说明

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 isActiveproperty 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.translatesAutoresizingMaskIntoConstraintsto false. When you do this, you also need to specify the widthand heightof the label with constraints because the frame no longer is used. Finally, you also should set the textAlignmentto .Centerso that your text is centered in your label.

正如@mustafa 和@kcstricks 在评论中指出的那样,您需要设置 label.translatesAutoresizingMaskIntoConstraintsfalse. 执行此操作时,您还需要指定带有约束的标签的widthheight,因为不再使用框架。最后,您还应该将 设置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

容器中的中心

enter image description here

在此处输入图片说明

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 NSLayoutConstraintStyle, however it is only available from iOS 9, so if you are supporting iOS 8 then you should still use NSLayoutConstraintStyle.
  • You will also need to add length and width constraints.
  • My full answer is here.
  • Anchor style 是比NSLayoutConstraintStyle更受欢迎的方法,但是它只在 iOS 9 中可用,所以如果你支持 iOS 8,那么你仍然应该使用NSLayoutConstraintStyle。
  • 您还需要添加长度和宽度约束。
  • 我的完整答案在这里

回答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 UILabeland add it to the UIButtonas 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)