Change Uiimageview Size to Match Image with Autolayout

Change UIImageView size to match image with AutoLayout

Auto Layout solution

Since establishing that you're using Auto Layout in your project, I have made a demo app to show you how you could change the image of the image view and adjust the height. Auto Layout will do this for you automatically, but the catch is that the photo you'll be using is coming from the users gallery and so they're likely to be very big and this.

So check out the app: https://bitbucket.org/danielphillips/auto-layout-imageview

The trick is to create a reference of the NSLayoutConstraint of the height of the image view. When you change your image, you need to adjust it's constant to the correct height given the fixed width.

Your other solution could be to set a contentMode on your image view, by using UIViewContentModeScaleAspectFit your image will always appear in full but will be locked to the bounds of the image view, which can change based on the Auto Layout constraints you have.

Initial reply

It looks like you've really over complicated this, unless I've missed something.

When you get a new image from the image picker, all you need to do is change the frame of the image view according to the UIImage size.

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
[self.imageView setImage:image];
self.imageView.frame = CGRectMake(self.imageView.frame.origin.x
self.imageView.frame.origin.y
image.size.width
image.size.height);
[self dismissViewControllerAnimated:YES completion:NULL];
}

Of course this is going to be potentially very large (it's using the original image which may be very large).

So let's lock the width to 280 points... this way we can always have the full image on screen in portrait mode.

So assuming your image size is 1000x800, and our image view perhaps is 280x100. We can calculate the correct height for the image view retaining the image view's width like this:

CGSize imageSize        = CGSizeMake(1000.0, 800.0);
CGSize imageViewSize = CGSizeMake(280.0, 100.0);

CGFloat correctImageViewHeight = (imageViewSize.width / imageSize.width) * imageSize.height;

self.imageView.frame = CGRectMake( self.imageView.frame.origin.x,
self.imageView.frame.origin.x,
CGRectGetWidth(self.imageView.bounds),
correctImageViewHeight);

With Auto Layout, how do I make a UIImageView's size dynamic depending on the image?

The image view's intrinsic size is already dependent on the size of the image. Your assumptions (and constraints are correct).

However, if you've set up your image view in interface builder and have not provided it with an image, then the layout system (interface builder) won't know how big your image view is supposed to be at compile time. Your layout is ambiguous because your image view could be many sizes. This is what throws the errors.

Once you set your image view's image property, then the image view's intrinsic size is defined by the size of the image. If you're setting the view at runtime, then you can do exactly what Anna mentioned and provide interface builder with a "placeholder" intrinsic size in the property inspector of the image view. This tells interface builder, "use this size for now, I'll give you a real size later". The placeholder constraints are ignored at runtime.

Your other option is to assign the image to the image view in interface builder directly (but I assume your images are dynamic, so this won't work for you).

Scaling UIImageView to fit width with AutoLayout

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.

iOS - Make UIImageView resize to fit UILabel with AutoLayout

For the first method, I assume you set the had the label and the image view have the same vertical and horizontal centers as well has the same height and width. The problem is the layout engine is assume the intrinsic size of the image is more important than the label. To change that you need to change hugging priority and the compression resistance of the views.Sample Image Go to the size inspect of the label (picture) and increase the hugging priority to required. This will for it's height and width to be it's intrinsic height and width. You could also decrease the image view's compression resistance, so it is more amendable to being sized down.

The constraints for the label:Sample Image

You can change the top and leading to place it in the appropriate spot in the view.

The constraints for the image view: Sample Image

How to resize UIImageView based on UIImage's size/ratio in Swift 3?

It looks like you want to resize an ImageView according to the image ratio and the container view's size, here is the example in Swift (Sorry,the former answer with a bug, I fixed it):

   let containerView = UIView(frame: CGRect(x:0,y:0,width:320,height:500))
let imageView = UIImageView()

if let image = UIImage(named: "a_image") {
let ratio = image.size.width / image.size.height
if containerView.frame.width > containerView.frame.height {
let newHeight = containerView.frame.width / ratio
imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
}
else{
let newWidth = containerView.frame.height * ratio
imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
}
}

Change size of UIImageView to fit different UIImages

Update width & height constraints:

I assume you're using autolayout. If so, you should change constraints' constant values instead of setting frames manually. Here is an example:

class ImageViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
@IBOutlet weak var widthConstraint: NSLayoutConstraint!

func setImage(image: UIImage) {
imageView.image = image
let screenSize = UIScreen.main.bounds.size

let imageAspectRatio = image.size.width / image.size.height
let screenAspectRatio = screenSize.width / screenSize.height

if imageAspectRatio > screenAspectRatio {
widthConstraint.constant = min(image.size.width, screenSize.width)
heightConstraint.constant = widthConstraint.constant / imageAspectRatio
}
else {
heightConstraint.constant = min(image.size.height, screenSize.height)
widthConstraint.constant = heightConstraint.constant * imageAspectRatio
}
view.layoutIfNeeded()
}
}

Note, that you also have to drag outlets for width and height constraints from storyboard to your viewController

Another solution without resizing UIImageView:

If other UI elements don't rely on UIImageView's frame and the only thing you care about is image appearance, you can just set content mode to Center or Top/Bottom/Right/Left etc:

Sample Image

Just set UIImageView's background to clear color

How to resize a fixed width and height UIImageView with auto layout

set imageView.clipToBounds = yes, and also set imageView.contentMode = UIViewContentModeScaleAspectFit;

Update
You are talking about imageView not the image, in that case it will not resize due to constant width and height, do one thing, create IBoutLet of constraint and change there values when required, or you can also set Aspect ratio with superView

UIImageView auto-created content size auto layout constraints overlap with trailing/leading constraints

I've googled the source of your view and found it at GitHub.
After looking into the implementation I found following code fragment:

- (CGSize)intrinsicContentSize
{
// Default to let UIImageView handle the sizing of its image, and anything else it might consider.
CGSize intrinsicContentSize = [super intrinsicContentSize];

// If we have have an animated image, use its image size.
// UIImageView's intrinsic content size seems to be the size of its image. The obvious approach, simply calling `-invalidateIntrinsicContentSize` when setting an animated image, results in UIImageView steadfastly returning `{UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric}` for its intrinsicContentSize.
// (Perhaps UIImageView bypasses its `-image` getter in its implementation of `-intrinsicContentSize`, as `-image` is not called after calling `-invalidateIntrinsicContentSize`.)
if (self.animatedImage) {
intrinsicContentSize = self.image.size;
}

return intrinsicContentSize;
}

It seems that in case of animatedImage the size will be reduced to the original image size.

The apple documentation tells about intrinsic content size:

In general, the intrinsic content size simplifies the layout, reducing the number of constraints you need

This can be interpreted as intrinsic content size usage already adds size constraints. For more informations about intrinsic content size usage see: Apple Documentation

One solution might be (not sure if there are some side effects) to use a subclass that overrides intrinsic content size like that:

override var intrinsicContentSize: CGSize {
return CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric)
}

BTW: Please provide a link to the sources in next questions, it save us time searching for it. Thanks!



Related Topics



Leave a reply



Submit