7
votes

I have a UIView inside of my layout in order to do some clipping and grouping, however the autolayout resizes it when shrunk. I want to give it a fixed height but the only option is to set the top and bottom space.

Is there a way to set an explicit height constraint?

7

7 Answers

5
votes

I just found this answer (Auto-Layout Constraint: How to make a view maintains its width/height ratio when resized?). This is what my implementation looks like:

- (void)awakeFromNib
{
    [super awakeFromNib];

    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:self
                                                            attribute:NSLayoutAttributeHeight
                                                            relatedBy:NSLayoutRelationEqual
                                                               toItem:nil
                                                            attribute:NSLayoutAttributeNotAnAttribute
                                                           multiplier:1
                                                             constant:self.frame.size.height];
    [self addConstraint:con1];
}
3
votes

Yes and No. In AutoLayout you cannot set a constraint for the size of a UIView, however you CAN prevent a UIView from being "compressed" past its intrinsic size.

This will effectively constrain a view, while avoiding the danger of having a parent view force a child view to be of a certain size (and thus remove the 'Auto' part of AutoLayout).

To set these priorities, you use: setContentCompressionResistancePriority:forAxis:

From the Apple UIView Documentation:

Custom views should set default values for both orientations on creation, based on their content, typically to NSLayoutPriorityDefaultLow or NSLayoutPriorityDefaultHigh. When creating user interfaces, the layout designer can modify these priorities for specific views when the overall layout design requires different tradeoffs than the natural priorities of the views being used in the interface.

Subclasses should not override this method.

Ok, so now we know how to assign a priority to avoid our view getting smaller than its intrinsic size, but how do we set the intrinsic size?

Well, if you are using a standard UI element, you are already set! But if your UIView is custom you will need to override - (CGSize)intrinsicContentSize to return the correct size. In here you can measure any sub-views that view has to calculate the correct dimensions - or if you are using artwork / constant sized elements you can return a hard-codded value.

Again, from the Apple UIView Documentation:

Custom views typically have content that they display of which the layout system is unaware. Overriding this method allows a custom view to communicate to the layout system what size it would like to be based on its content. This intrinsic size must be independent of the content frame, because there’s no way to dynamically communicate a changed width to the layout system based on a changed height, for example.

Apple strongly advises against inspecting anything outside of your UIView (like getting the size of your super view and tweaking that) as that's not what AutoLayout is for (and can cause bad headaches down the road).

3
votes
  1. Select your view in the Inspector on the left of Interface Builder.
  2. Ctrl drag a line from the view to itself.

=> A popover appears where you can set explicit height and width constraints.

3
votes

Swift code of eckyzero code.

let heightConstraint = NSLayoutConstraint(item: yourView, 
                                      attribute: .Height, 
                                       relatedBy: .Equal, 
                                             toItem: nil, 
                              attribute: .NotAnAttribute, 
                             multiplier: 1, constant: 80)//your desired height

yourView.addConstraint(heightConstraint)
1
votes

Yes, you can give it a fixed height.

You need to specify at least two constraints in each dimension, so you can't delete the top or bottom space until you've added the fixed height constraint. In IB, select your view, then in the bottom right of the view editor there's a button with three icons, press the middle one and select 'Height'. This adds the height constraint. Now you can go and delete the bottom or top space and you can edit the height constraint if you need to by clicking on it in the size inspector.

0
votes

You don't need to give it a top space and bottom space. If you have a bottom constraint of say 8 pixels from the bottom of the superview, it will always try to resize the child view to stay within the super view (depending if you set priorities).

You could give the height constraint a priority higher then the bottom space constraint, so when they are in conflict, it will choose to enforce the height constraint and ignore the bottom constraint.

For constraints, you do not need 4 constraints (top, bottom, left, and right); you only ever need 2: vertical and horizontal. The rest is figured by autolay out.

Just remove the bottom constraint and the child view should get clipped.

-4
votes

try this

view.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;