I'm trying to place an UIImageView
in the parent view's center. Image must keep its original aspect ratio and also it shouldn't exceed parent's bounds. So landscape images should be limited by parent's width and portrait images should occupy as much vertical space as needed keeping original ratio.
Sounds like quite a simple task for AutoLayout, right? Here's my setup for UIImageView
:
- center vertically in parent
- center horizontally in parent
- imageView.width <= superview.width
- imageView.height <= superview.height
I also set contentMode
to Aspect Fit
. Everything works really great for small images which are smaller than device screen but for some reason my UIImageView
takes more space than its underlying UIImage
for large images (notice the green background - imageView.backgroundColor = [UIColor greenColor]
).
Why is this happening? I am not an AutoLayout expert by my constraints look reasonable to me. If I use smaller images like 200x400 then UIImageView
takes exactly 200x400 points on the screen with no extra green areas.
I'd like to add borders and rounded corners which obviously won't work properly in this case.
This is happenning because you've set width and height constraints as <=.
For small images imageView's frame is calculated without any issues and all constraints are satisfied. But when a big image is set, imageView's size is going to be set so that the image fits, but at the same it is limited by the size of the superview (screen size).
- If you know aspect ratio for sure, you can set it as a constraint and
you won't see any green background.
- Otherwise just leave your
constraints as they are and set background color to clear color. This
way any unoccupied zones will be transparent and any image you set
will take maximum space in at least one dimension.
Edit:
Probably not the best solution, kind of oldschool. You can add strict width and height constraints and calculate them manually using image's aspectRatio:
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
@IBOutlet weak var widthConstraint: NSLayoutConstraint!
func setImage(image: UIImage) {
imageView.image = image
let screenSize = UIScreen.main.bounds.size
let imageAspectRatio = image.size.width / image.size.height
let screenAspectRatio = screenSize.width / screenSize.height
if imageAspectRatio > screenAspectRatio {
widthConstraint.constant = min(image.size.width, screenSize.width)
heightConstraint.constant = widthConstraint.constant / imageAspectRatio
}
else {
heightConstraint.constant = min(image.size.height, screenSize.height)
widthConstraint.constant = heightConstraint.constant * imageAspectRatio
}
view.layoutIfNeeded()
}
Try to check "Clip to Bounds" for imageView in Interface Builder
Clip to Bounds Image View
and you must have a well-defined height and width, not "<="