UIImageView renders the size of an image incorrectly. Using Scale Aspect Fit, if the UIImageView is a square the image is the correct aspect ratio with transparency in the areas the image does not fill.
//Image is Square & Correct Size
var imageView = UIImageView(frame: CGRectMake(0, 50, 320, 320))
imageView.clipsToBounds = true
imageView.contentMode = UIViewContentMode.ScaleAspectFit
//Image is Rectangle & Incorrect Size
var imageView = UIImageView(frame: CGRectMake(0, 50, 320, 450))
imageView.clipsToBounds = true
imageView.contentMode = UIViewContentMode.ScaleAspectFit
The UIImageView needs to touch the edges and have transparent space at the top and bottom of the screen and the image inside needs to keep its original ratio rather than stretching taller. I have attached two images of how the image inside the UIImageView is rendering.
I added an autoresizing mask to the UIImageView and it now displays the correct ratios.
imageView.autoresizingMask = UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleWidth
imageView.contentMode = UIViewContentMode.ScaleAspectFit
This answer helped me: Captured photo is stretched with AVCaptureSession sessionPreset = AVCaptureSessionPresetPhoto as I was using an image that was taken through the phones camera.
I was having the same issue, and what fixed it for me was making sure to set the imageView image after the content mode was set. ie:
self.imageView.contentMode = UIViewContentMode.ScaleAspectFit
self.imageView.image = imageChosen
Cheers
Swift 3 version of your code:
imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin]
imageView.contentMode = .scaleAspectFit // OR .scaleAspectFill
imageView.clipsToBounds = true
That's the intended behaviour for UIViewContentMode.ScaleAspectFit
. From the docs:
UIViewContentModeScaleAspectFit
The option to scale the content to fit
the size of the view by maintaining the aspect ratio. Any remaining
area of the view’s bounds is transparent.
It seems from what you describe that you need UIViewContentMode.ScaleAspectFill
UIViewContentModeScaleAspectFill
The option to scale the content to
fill the size of the view. Some portion of the content may be clipped
to fill the view’s bounds.
There is a great solution here: by olearyj234 .
and it helped me a lot. I suggest taking a look. Also, here is his code in swift 4 and Xcode 9.2:
class ScaledHeightImageView: UIImageView {
override var intrinsicContentSize: CGSize {
if let myImage = self.image {
let myImageWidth = myImage.size.width
let myImageHeight = myImage.size.height
let myViewWidth = self.frame.size.width
let ratio = myViewWidth/myImageWidth
let scaledHeight = myImageHeight * ratio
return CGSize(width: myViewWidth, height: scaledHeight)
}
return CGSize(width: -1.0, height: -1.0)
}
}
Swift 5
You can apply UIView.ContentMode.scaleAspectFit only for UIImageView
like this:
let logoImage:UIImage = UIImage(named: "my_logo")!
let logoImageView = UIImageView(image: logoImage)
logoImageView.contentMode = UIView.ContentMode.scaleAspectFit
return logoImageView