Creating layout constraints programmatically Creating layout constraints programmatically ios ios

Creating layout constraints programmatically


When using Auto Layout in code, setting the frame does nothing. So the fact that you specified a width of 200 on the view above, doesn't mean anything when you set constraints on it. In order for a view's constraint set to be unambiguous, it needs four things: an x-position, a y-position, a width, and a height for any given state.

Currently in the code above, you only have two (height, relative to the superview, and y-position, relative to the superview). In addition to this, you have two required constraints that could conflict depending on how the view's superview's constraints are setup. If the superview were to have a required constraint that specifies it's height be some value less than 748, you will get an "unsatisfiable constraints" exception.

The fact that you've set the width of the view before setting constraints means nothing. It will not even take the old frame into account and will calculate a new frame based on all of the constraints that it has specified for those views. When dealing with autolayout in code, I typically just create a new view using initWithFrame:CGRectZero or simply init.

To create the constraint set required for the layout you verbally described in your question, you would need to add some horizontal constraints to bound the width and x-position in order to give a fully-specified layout:

[self.view addConstraints:[NSLayoutConstraint    constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"    options:NSLayoutFormatDirectionLeadingToTrailing    metrics:nil    views:NSDictionaryOfVariableBindings(myView)]];[self.view addConstraints:[NSLayoutConstraint    constraintsWithVisualFormat:@"H:[myView(==200)]-|"    options:NSLayoutFormatDirectionLeadingToTrailing    metrics:nil    views:NSDictionaryOfVariableBindings(myView)]];

Verbally describing this layout reads as follows starting with the vertical constraint:

myView will fill its superview's height with a top and bottom padding equal to the standard space. myView's superview has a minimum height of 748pts. myView's width is 200pts and has a right padding equal to the standard space against its superview.

If you would simply like the view to fill the entire superview's height without constraining the superview's height, then you would just omit the (>=748) parameter in the visual format text. If you think that the (>=748) parameter is required to give it a height - you don't in this instance: pinning the view to the superview's edges using the bar (|) or bar with space (|-, -|) syntax, you are giving your view a y-position (pinning the view on a single-edge), and a y-position with height (pinning the view on both edges), thus satisfying your constraint set for the view.

In regards to your second question:

Using NSDictionaryOfVariableBindings(self.myView) (if you had an property setup for myView) and feeding that into your VFL to use self.myView in your VFL text, you will probably get an exception when autolayout tries to parse your VFL text. It has to do with the dot notation in dictionary keys and the system trying to use valueForKeyPath:. See here for a similar question and answer.


Hi I have been using this page a lot for constraints and "how to". It took me forever to get to the point of realizing I needed:

myView.translatesAutoresizingMaskIntoConstraints = NO;

to get this example to work. Thank you Userxxx, Rob M. and especially larsacus for the explanation and code here, it has been invaluable.

Here is the code in full to get the examples above to run:

UIView *myView = [[UIView alloc] init];myView.backgroundColor = [UIColor redColor];myView.translatesAutoresizingMaskIntoConstraints = NO;  //This part hung me up [self.view addSubview:myView];//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748[self.view addConstraints:[NSLayoutConstraint                           constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|"                           options:NSLayoutFormatDirectionLeadingToTrailing                           metrics:nil                           views:NSDictionaryOfVariableBindings(myView)]];[self.view addConstraints:[NSLayoutConstraint                           constraintsWithVisualFormat:@"H:[myView(==200)]-|"                           options:NSLayoutFormatDirectionLeadingToTrailing                           metrics:nil                           views:NSDictionaryOfVariableBindings(myView)]];


Swift version

Updated for Swift 3

This example will show two methods to programmatically add the following constraints the same as if doing it in the Interface Builder:

Width and Height

enter image description here

Center in Container

enter image description here

Boilerplate code

override func viewDidLoad() {    super.viewDidLoad()    // set up the view    let myView = UIView()    myView.backgroundColor = UIColor.blue    myView.translatesAutoresizingMaskIntoConstraints = false    view.addSubview(myView)    // Add constraints code here (choose one of the methods below)    // ...}

Method 1: Anchor Style

// width and heightmyView.widthAnchor.constraint(equalToConstant: 200).isActive = truemyView.heightAnchor.constraint(equalToConstant: 100).isActive = true// center in containermyView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = truemyView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Method 2: NSLayoutConstraint Style

// width and heightNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = trueNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true// center in containerNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = trueNSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.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.
  • See also the Programmatically Creating Constraints documentation.
  • See this answer for a similar example of adding a pinning constraint.