3

I have a UIImageView on top of a UIScrollView, and I would like it to fit the device width, its height then being automatically set so that the image ratio is preserved.

I am using Auto Layout, so I used constraints to bind the UIImageView to the top, left and right edges of the screen. My problem is, the UIImageView automatically resizes its frame to fit the UIImage height. And I cannot really change this frame afterwards, as it lets a gap between the UIImageView and the other UI elements, that are supposed to be just under it.

I found a workaround by manually resizing the image to the good size before putting it into the UIImageView, but it isn't very efficient, and it creates problem when the view is resized, for example when the device rotates.

Has anyone found a way to force the UIImageView to change its frame and to keep it rather than using the image's size ?

Pierre

EDIT : I added screenshots so you can see the problem.

screenshot

And here is the expected result :

expected result

Pierre
  • 372
  • 2
  • 16
  • Have you played with the content hugging priorities of the image view? Try lowering them. – Zev Eisenberg Feb 26 '15 at 04:26
  • They are already at 250, and no constraint is lower than them. I tried to put them at 249, and it didn't change anything. Again, I don't think that is the problem because the frame height is set to the image height when image is put into imageView. As everything is put on a scrollView, the imageView takes all the height it wants. – Pierre Feb 26 '15 at 11:21

2 Answers2

8

OK, I found a suitable solution to my problem.

I calculate the correct height that I want for my picture like this :

correctedHeight = screenWidth / width * height

After that, I add a height constraint programmatically in the updateViewConstraints method.

I use this code :

[imageView addConstraint:[NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant: correctImageViewHeight]];

Two things to think of after that :

  • removing the constraint each time this method is called (otherwise you end up with conflicting constraints). To achieve this, I use [imageView removeConstraint: imageView.constraints.lastObject] ;
  • putting[super updateViewConstraints] ; inside the method. If you forget, it crashes.

I haven't done it yet, but I can easily see how I could update my correctHeight variable when the device rotates.

Pierre
  • 372
  • 2
  • 16
  • 4
    you can get rid of `addConstraint` and `removeConstraint` by adding the constraint in the Interface Buider and linking it to an outlet in your code, then you only have to update the constant property of the constraint – Jorge Arimany Oct 22 '15 at 18:12
  • thats solved my problem too, and I did like Jorge said, just add a IBOutlet for the Height Constraint instead of remove and add constraint. I'm trying to use only AutoLayout but sometimes the code is necessary – Yuri Natividade Aug 09 '17 at 19:50
  • 10x, I did something similar in swift: if let imageSize = imageView.image?.size, imageSize.height != 0 { let ratio = imageSize.width / imageSize.height imageView.aspectRatio(ratio) } else { imageView.aspectRatio(1) } – Kamen Dobrev Apr 15 '21 at 15:29
0

Use the following code

imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.autoresizingMask =   
    ( UIViewAutoresizingFlexibleBottomMargin
    | UIViewAutoresizingFlexibleHeight
    | UIViewAutoresizingFlexibleLeftMargin
    | UIViewAutoresizingFlexibleRightMargin
    | UIViewAutoresizingFlexibleTopMargin
    | UIViewAutoresizingFlexibleWidth );

Can you provide code?

ossamacpp
  • 656
  • 5
  • 11
  • The UIViewContentModeScaleAspectFill makes the image fill the entire imageView. However, the latter is still the same height as the original image. – Pierre Feb 26 '15 at 11:22