30

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.

ImageView with correct Aspect ImageView with wrong Aspect

George Grover
  • 1,134
  • 2
  • 10
  • 17

6 Answers6

46

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.

Community
  • 1
  • 1
George Grover
  • 1,134
  • 2
  • 10
  • 17
  • 8
    Swift 3 code: imageView.autoresizingMask = [.flexibleTopMargin, .flexibleHeight, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin, .flexibleWidth] – Markymark Dec 17 '16 at 08:22
  • 1
    @george Grover This answer is outdated, kindly update it. – iPhone 7 Aug 29 '17 at 10:29
24

Swift 3 version of your code:

imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin]
imageView.contentMode = .scaleAspectFit // OR .scaleAspectFill
imageView.clipsToBounds = true
Frank Eno
  • 2,581
  • 2
  • 31
  • 54
23

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

Paul G
  • 829
  • 7
  • 11
7

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.

Cezar
  • 55,636
  • 19
  • 86
  • 87
  • I want the image to fit the box e.g. when the box gets taller the sides touch the edges and there remains to be a transparent space at the top and bottom. ScaleAspectFill doesn't give this outcome, how would you suggest to force it to touch the sides but not top and bottom? – George Grover Jan 15 '15 at 11:34
  • Right, I thought you were saying you didn't want the transparency thing. Sorry I misunderstood you. – Cezar Jan 15 '15 at 11:41
  • Sorry, I didn't explain myself properly - updated my question to clear it up. Do you have any ideas on why the image is growing vertically rather than horizontally? – George Grover Jan 15 '15 at 11:44
  • Nope. And the problem doesn't happen on a sample project I've just set up, using your code and your image. Weird. – Cezar Jan 15 '15 at 12:02
2

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
Álvaro Agüero
  • 4,494
  • 1
  • 42
  • 39
1

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)
    }

}
Hamid Hoseini
  • 1,560
  • 17
  • 21