Swift UIImageView Stretched Aspect
Asked Answered
G

6

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

Ger answered 15/1, 2015 at 10:58 Comment(0)
G
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.

Ger answered 19/1, 2015 at 14:23 Comment(2)
Swift 3 code: imageView.autoresizingMask = [.flexibleTopMargin, .flexibleHeight, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin, .flexibleWidth]Shortlived
@george Grover This answer is outdated, kindly update it.Unwholesome
T
24

Swift 3 version of your code:

imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleBottomMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin]
imageView.contentMode = .scaleAspectFit // OR .scaleAspectFill
imageView.clipsToBounds = true
Twinscrew answered 21/12, 2016 at 15:35 Comment(0)
P
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

Pisgah answered 22/11, 2015 at 1:18 Comment(1)
Solved it for me. Absolutely ridiculous that I spent three hours trying to solve this bug and this was the solution.Loupe
B
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.

Benita answered 15/1, 2015 at 11:31 Comment(4)
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?Ger
Right, I thought you were saying you didn't want the transparency thing. Sorry I misunderstood you.Benita
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?Ger
Nope. And the problem doesn't happen on a sample project I've just set up, using your code and your image. Weird.Benita
C
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
Cottrell answered 31/12, 2019 at 14:15 Comment(0)
P
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)
    }

}
Paediatrician answered 3/5, 2018 at 18:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.