33

I have a question about setting the size of a view to which i'm applying some layout constraints.
How can I define the size of the view without defining its frame?

I'm trying to create a view that has its height fixed and has an origin at the screen origin. It fills the width of the view, so that when the device rotates the view extends to the width of the screen. This is what I've got so far...

self.containerView = [[HitTestContainerView alloc] init];
[self.containerView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.containerView];

NSDictionary *viewsDictionary = @{@"view":self.containerView};
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-250-|" options:0 metrics:nil views:viewsDictionary];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:verticalConstraints];
[self.view addConstraints:horizontalConstraints];

The problem is I can't get anything to show up on the screen unless I set the frame of that containerView. What is the correct way to do this without using Interface Builder?

JJD
  • 50,076
  • 60
  • 203
  • 339
Sean Danzeiser
  • 9,141
  • 12
  • 52
  • 90
  • Have you tried to continuously update the size of the parent view and return it in [`intrinsicContentSize`](http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/AutolayoutPG/Articles/dividingResponsibility.html), [see here](http://stackoverflow.com/a/13034819/356895). – JJD Oct 29 '12 at 09:57
  • Why am i getting an incompatible pointer types sending NSArray*__strong to parameter of type NSLayout constraint using your example? constraintsWithVisualFormat is returning an NSArray but addConstraint wants an NSLayoutConstraint. what gives? – topwik May 30 '13 at 21:48
  • `constraintsWithVisualFormat` always returns an array of `NSLayoutConstraint`s. It is confusing but it makes sense since the visual format may specify more then one constraint. – Evan Moran Jul 24 '13 at 22:21

5 Answers5

53

I wrote a little tool that will assist you with this:

http://autolayoutconstraints.com

Here is the answer to your question autogenerated by the tool

Objective-C

// align view from the left and right
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view]-10-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];

// width constraint
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[view(==250)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];

// height constraint
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[view(==50)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(view)]];

Swift

// align view from the left and right
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));

// width constraint
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[view(==250)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));

// height constraint
self.containerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[view(==50)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view": view]));
Chad Cache
  • 9,668
  • 3
  • 56
  • 48
47

To define the height and width of a view using layout constraints, you, uh, define the height and width of the view using layout constraints. For example, you are already saying:

NSArray *verticalConstraints = 
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-250-|" 
    options:0 metrics:nil views:viewsDictionary];

So you could just change that to:

NSArray *verticalConstraints = 
[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(50)-[view(40)]" 
    options:0 metrics:nil views:viewsDictionary];

Now the view will be 50 pixels from the top of its superview, and 40 pixels tall.

Alternatively you can use constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant: to set the height constraint; the toItem will be nil, of course, since there is no relationship to another view.

matt
  • 515,959
  • 87
  • 875
  • 1,141
10

Better later than never...

For Storyboard, IB and Swift:

Just control-drag your constraint like any other control to your viewController

@IBOutlet weak var spaceToTopThatIDecided: NSLayoutConstraint!

then change it simply:

spaceToTopThatIDecided.constant = 44

That's all!

Luismi
  • 1,071
  • 1
  • 13
  • 18
4

you don’t have to use addConstraints:() methods

- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_MAC(10_7);

// This method is deprecated and should be avoided.  Instead, set NSLayoutConstraint's active property to YES.

- (void)addConstraints:(NSArray *)constraints NS_AVAILABLE_MAC(10_7);   

// This method is deprecated and should be avoided.  Instead use

+[NSLayoutConstraint activateConstraints:].

// are so need to use

+ (void)activateConstraints:(NSArray *)constraints NS_AVAILABLE(10_10, 8_0);

// then set like

NSView *view,*containerView;
view =//superview
containerView=//subview
[view addSubview:containerView];

// adding constraints

[containerView setTranslatesAutoresizingMaskIntoConstraints:NO];

// about it read from Apple documentation

// then add constraints like

[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[view]-50-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(containerView)]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(containerView)]];

// thats it.

ERbittuu
  • 968
  • 8
  • 19
0

Swift 4: You can manage the width and height, in addition to leading, trailing and top and bottom space just with the below 2 options

 //1 . left and right spacing
    theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[view]-16-|", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))

 //2. top and bottom spacing
    theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[view]-16-|", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))

OR To be more specific , and to have separate constraints for W,H,left spacing, Top spacing, you can do as below

 //left only spacing
        theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-16-[view]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))

//top only spacing
        theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-16-[view]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))

//width
        theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[view(==130)]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))

//height
        theContentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[view(==100)]", options:NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":nibView]))
Naishta
  • 11,885
  • 4
  • 72
  • 54