Home > database >  UICollectionView UIImage with .aspectFit is changing contraints
UICollectionView UIImage with .aspectFit is changing contraints

Time:01-16

I have a very simple collection view that has images in it, my Cell class looks like this:

class ImageListCell: UICollectionViewCell {
    @IBOutlet weak var btnDelete: UIButton! {
        didSet {
            btnDelete.layer.cornerRadius = btnDelete.frame.height / 2
        }
    }
    @IBOutlet weak var imageView: UIImageView!
    
    @IBAction func btnDeleteTap(_ sender: Any) {
        print("Delete image")
    }
}

The cell's imageView constraints have some padding at the top and trailing edge:

enter image description here

If I color the ImageListCell background red and the imageView background green, this is what it looks like:

enter image description here

Which is 100% correct!

However, if all I do is add an image to imageView the contraints get all goofy?

enter image description here

This only happens in .aspectFit, if I change it to .aspectFill it works but the images are all stretched.

enter image description here

I made sure I'm not adjusting cell size or anything and Estimated Size on the collection view is turned off.

Does anyone have any idea why .aspectFill is overriding my constraints?

CodePudding user response:

  • Nothing is happening to your constraints. The image view is exactly where you put it.

  • In the first picture-with-the-image, .aspectFit is behaving exactly as expected: no empty space is left within the image view around the outside of the image, and the image is not distorted. If you don't like the fact that the image is "leaking" off the right side, that's merely because you forgot to set your image view's clipsToBounds to true.

  • The second picture-with-the-image is not .aspectFill as you claim. It is .scaleToFill. There is a huge difference. So your statement of the phenomena is not even correct. .scaleToFill can distort the image; .aspectFill would not do that (but it would display the green background of the image view).

CodePudding user response:

There are a few things in your question that seem incorrect.

You are referring to content modes with values such as .aspectFit and .aspectFill. In Swift code there are no such values. These would be .scaleAspectFit and .scaleAspectFill. In a storyboard the "Content Mode" property of a view can be things like "Aspect Fit", "Aspect Fill", and others.

Since you setup your cell in a storyboard I'll refer to the storyboard property settings. Everything I describe applies to the UIImageView outlet in your collection view cell.

The first screenshot you show with what you claim to be as .aspectFit would only happen if you set the "Content Mode" to "Aspect Fill" (not "Aspect Fit" as you claim) and you turned off the "Clips to Bounds" setting. With "Aspect Fill" set, a wide image will correctly fill the height of the image view (which is why you still see the top red border, but the left and right sides of the image would overflow outside the image view (which is why you can't see the right red border). If "Clip to Bounds" was checked, the right red border would be visible. The collection view cell itself clips all of its content which prevents the overflowing image from spilling out of the cell's frame.

The second screenshot you show with what you claim to be as .aspectFill would be the result of setting "Content Mode" to "Scale To Fill", not "Aspect Fill". The result would be the same whether "Clip to Bounds" was checked or not. "Scale to Fill" distorts the image as needed to fully fill the height and width of the image view.

Based on your description you want to set "Content Mode" to "Aspect Fit". While not really needed for "Aspect Fit", it wouldn't hurt to enable "Clip to Bounds". This will show the entire image with appropriate green borders and no distortion.

tl;dr - your constraints are fine. You are not really setting the image view's content mode to "Aspect Fit" in the first image picture. You are setting it to "Aspect Fill" and "Clip to Bounds" is off.

If you want to do this in code you want:

imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true // optional for .scaleAspectFit
  • Related