Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change Auto Layout constraints after they are set when using constraintEqualToAnchor()?

Tags:

I try to set up a view with AutoLayout constraints by using constraintEqualToAnchor():

override func viewDidLoad() {     super.viewDidLoad()      let myView = UIView()     myView.backgroundColor = UIColor.orangeColor()     myView.translatesAutoresizingMaskIntoConstraints = false     view.addSubview(myView)      myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor).active = true     myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true     myView.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true     myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true      /******************************************/     /* I try to change one of the constraints */     /******************************************/     myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100).active = true   } 

In the last line of code, I try to change one of the constraints. I thought it would work but it gives some error in the console log

"<NSLayoutConstraint:0x7fb53a5180d0 H:|-(0)-[UIView:0x7fb53a5190b0](LTR)   (Names: '|':UIView:0x7fb53a519240 )>", "<NSLayoutConstraint:0x7fb53a51f660 H:[UIView:0x7fb53a519240]-(-100)-[UIView:0x7fb53a5190b0](LTR)>", "<NSLayoutConstraint:0x7fb53a711ee0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fb53a519240(414)]>" 

When using constraintEqualToAnchor()?, what's the right way to change the constraint later after I have set them?

like image 674
Joe Huang Avatar asked Dec 21 '15 08:12

Joe Huang


People also ask

What are two properties that auto Layout constraints control on a Uiview?

Auto Layout defines margins for each view. These margins describe the preferred spacing between the edge of the view and its subviews. You can access the view's margins using either the layoutMargins or layoutMarginsGuide property. The layoutMargins property lets you get and set the margins as a UIEdgeInsets structure.

How do I use Autolayout constraints?

Auto Layout defines your user interface using a series of constraints. Constraints typically represent a relationship between two views. Auto Layout then calculates the size and location of each view based on these constraints. This produces layouts that dynamically respond to both internal and external changes.

What is Autolayout in Swift?

Auto Layout constraints allow us to create views that dynamically adjust to different size classes and positions. The constraints will make sure that your views adjust to any size changes without having to manually update frames or positions.


2 Answers

You need to deactivate the previous constraint when activating a new one so that you don't end up over constraining your view. To do that, store a reference to each of the constraints as a property in your ViewController and then set the active property of the old constraint to false before creating and activating the new constraint:

Swift 2.x:

class ViewController: UIViewController {     var leftConstraint: NSLayoutConstraint?     var trailingConstraint: NSLayoutConstraint?     var topConstraint: NSLayoutConstraint?     var bottomConstraint: NSLayoutConstraint?      override func viewDidLoad() {         super.viewDidLoad()          let myView = UIView()         myView.backgroundColor = UIColor.orangeColor()         myView.translatesAutoresizingMaskIntoConstraints = false         view.addSubview(myView)          leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor)         leftConstraint?.active = true          trailingConstraint = myView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor)         trailingConstraint?.active = true          topConstraint = myView.topAnchor.constraintEqualToAnchor(view.topAnchor)         topConstraint?.active = true          bottomConstraint = myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor)         bottomConstraint?.active = true          /******************************************/         /* I try to change one of the constraints */         /******************************************/         leftConstraint?.active = false         leftConstraint = myView.leftAnchor.constraintEqualToAnchor(view.rightAnchor, constant: -100)         leftConstraint?.active = true     } } 

Update for Swift 3 syntax:

class ViewController: UIViewController {     var leftConstraint: NSLayoutConstraint?     var trailingConstraint: NSLayoutConstraint?     var topConstraint: NSLayoutConstraint?     var bottomConstraint: NSLayoutConstraint?      override func viewDidLoad() {         super.viewDidLoad()          let myView = UIView()         myView.backgroundColor = UIColor.orange         myView.translatesAutoresizingMaskIntoConstraints = false         view.addSubview(myView)          leftConstraint = myView.leftAnchor.constraint(equalTo: view.leftAnchor)         leftConstraint?.isActive = true          trailingConstraint = myView.trailingAnchor.constraint(equalTo: view.trailingAnchor)         trailingConstraint?.isActive = true          topConstraint = myView.topAnchor.constraint(equalTo: view.topAnchor)         topConstraint?.isActive = true          bottomConstraint = myView.bottomAnchor.constraint(equalTo: view.bottomAnchor)         bottomConstraint?.isActive = true          /******************************************/         /* I try to change one of the constraints */         /******************************************/         leftConstraint?.isActive = false         leftConstraint = myView.leftAnchor.constraint(equalTo: view.rightAnchor, constant: -100)         leftConstraint?.isActive = true     } } 
like image 58
vacawama Avatar answered Oct 23 '22 04:10

vacawama


Here is an example declaring a constraint c which will be referenced later in time. We set a new constant value and then call layout on the superview.

myView.translatesAutoresizingMaskIntoConstraints = false  var constraints: [NSLayoutConstraint] = [     myView.topAnchor.constraintEqualToAnchor(view.topAnchor),     myView.leftAnchor.constraintEqualToAnchor(view.leftAnchor),     myView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor) ]          let c = myView.rightAnchor.constraintEqualToAnchor(view.rightAnchor)        constraints.append(c)     view.addSubview(myView) NSLayoutConstraint.activateConstraints(constraints)  // Some time later c.constant = -100 view.setNeedsLayout() 
like image 44
Lucas Derraugh Avatar answered Oct 23 '22 04:10

Lucas Derraugh