Programmatically Add CenterX/CenterY Constraints

前端 未结 7 740

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 w

相关标签:
7条回答
  • 2020-11-29 18:38

    Update for 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()

    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([
        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 before creating 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.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.

        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)
    
    0 讨论(0)
  • 2020-11-29 18:44

    Center in container

    The code below does the same thing as centering in the 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(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 use NSLayoutConstraint Style.
    • You will also need to add length and width constraints.
    • My full answer is here.
    0 讨论(0)
  • 2020-11-29 18:52

    The ObjectiveC equivalent is:

        myView.translatesAutoresizingMaskIntoConstraints = NO;
    
        [[myView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor] setActive:YES];
    
        [[myView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] setActive:YES];
    
    0 讨论(0)
  • 2020-11-29 18:53

    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 * 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; 
    
    0 讨论(0)
  • 2020-11-29 18:55

    In Swift 5 it looks like this:

    label.translatesAutoresizingMaskIntoConstraints = false
    label.centerXAnchor.constraint(equalTo: vc.view.centerXAnchor).isActive = true
    label.centerYAnchor.constraint(equalTo: vc.view.centerYAnchor).isActive = true
    
    0 讨论(0)
  • 2020-11-29 18:57

    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:

        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)
    
    0 讨论(0)
提交回复
热议问题