Mário Klein Mário Klein - 2 months ago 14
iOS Question

UIImageView with auto-layout and max size keeping aspect ratio

I have a UIImageView generated in source (programmatically). That UIImageView needs to have a max size, for booth width and height. In this view I load a image from URL and set after the download ends. I don't know, previously, what the size of the image, but I need to keep the aspect ratio and make the UIImageView with a size that maintains that aspect. If the image is smaller, in one or both dimension, I want the UIImageView has the size necessary to maintain the aspect ratio without stretch the image.

I'll give two examples considering the max size for UIImageView with 250 X 350.

Example 1:

The image size is 800 X 800.
The size of UIImageView needs to be 250 X 250.

Example 2:

The image size is 200 X 250.
The size of UIImageView needs to be 200 X 250.

How can I do this with auto-layout.

Thanks for help!


You'll need three constraints here. One that maintains the aspect ratio, one that makes sure the width is no larger than the maximum, and one that makes sure the height is no larger than the maximum. As of August 2016, Interface Builder does not support constraints referencing other constraints, so – at a minimum – the aspect ratio constraint must be done in code.

The aspect ratio is the only one that takes any thinking. Let V_w and V_h be the width and height, respectively, of your image view. Let I_w and I_h be the width and height, respectively, of your image. Then, to maintain the image's aspect ratio, the following equation must remain true:

V_w / V_h = I_w / I_h

Or, equivalently:

V_w = (I_w / I_h) * V_h

Ok, looking good. Let's write some code. In this code, I assume you have MAX_HEIGHT and MAX_WIDTH defined earlier.

CGFloat aspectRatioMult = (imageView.image.size.width / imageView.image.size.height);

// Constrain the desired aspect ratio
[imageView addConstraint:
  [NSLayoutConstraint constraintWithItem:imageView

// Constrain height
[imageView addConstraints:
  [NSLayoutConstraint constraintsWithVisualFormat:@"H:[imageView(<=max)]"
                                          metrics:@{@"max" : @(MAX_HEIGHT)}
                                            views:@{@"imageView" : imageView}]];

// Constrain width
[imageView addConstraints:
  [NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageView(<=max)]"
                                          metrics:@{@"max" : @(MAX_WIDTH)}
                                            views:@{@"imageView" : imageView}]];