4

I have a UIImage View that is set up using AutoLayout and constraints. I fit the image to the Image View using

     self.selectPhoto.contentMode = UIViewContentModeScaleAspectFit;
     NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:0 toItem:self.selectPhoto attribute:NSLayoutAttributeTop multiplier:1 constant:-10];
     NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.selectPhoto attribute:NSLayoutAttributeBottom relatedBy:0 toItem:self.caption attribute:NSLayoutAttributeTop multiplier:1 constant:-35];
     [self.view addConstraint:topConstraint];
     [self.view addConstraint:bottomConstraint];
     self.selectPhoto.image= existingImage;

It works great. Because the UIImageView is set up using AutoLayout, and the UIImage is shown using Aspect Fit, I do not know the exact frame of the image. I want the upper left hand corner of the image to be at 0,0 in the image view because I have another smaller image which the user can move around on top of it. Image 1

For example : Because of the orientation of the waterfall image the upper left hand corner is 0,23ish in the UIImageView. When the image height > image width the origin (of the image view) is 66,0. This is a problem because I want to then draw the user context of both images and save as a new image. I can't do this because I don't know where the 2 Months image is placed on the waterfall image because I don't know the origin of the waterfall image. I know where the 2 Months image is on the image VIEW, but the image doesn't take up the entire imageView. Because of the AutoLayout and Aspect Fit it differs depending on the size/orientation of the image. I added the 2Months Pan gesture to the waterfall image view, but the origins don't line up. The code for the pan gesture which is attached to the 2Months view is as follows

-(void) handlePan:(UIPanGestureRecognizer *)recognizer {
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
    self.itemToEdit.stickerLocation= recognizer.view.frame;
    NSLog(@"The location of the sticker is %f and y is %f", recognizer.view.frame.origin.x, recognizer.view.frame.origin.y);
}

Is there a way to fit the UIImageView to the actual displayed UIImage? Basically I want to do something like self.selectPhoto.frame = self.selectPhoto.image.frame Which I can't do.

In summary : How do I know the absolute origin of my imageView after it has been placed using AutoLayout and Aspect fit?

leenyburger
  • 1,198
  • 1
  • 11
  • 23

1 Answers1

2

Based on this Stack Overflow answer, we can get the size of a UIImage by accessing its size property.

So, from here, the easiest way to proceed is using autolayout.

Set up your storyboard or xib with your image view on it. Go ahead and give your image view an explicit width and height constraint. Now, fill in the rest of the constraints around the image view. Keep in mind, however, that this explicit width/height on the image view will be changing as we drop different images into the image view, so our other autolayout constraints must keep this in mind.

Now, add an IBOutlet for our explicit height and width constraints. This can be done the same way we add an outlet for any other UI element. Just Ctrl+drag from the constraint in IB to the source file.

Now we have something like this:

@property (nonatomic, weak) NSLayoutConstraint *imageHeight;
@property (nonatomic, weak) NSLayoutConstraint *imageWidth;

Now, each time we change the image view's image, we update the constant part of these constraints:

self.imageHeight.constant = newImage.size.height;
self.imageWidth.constant = newImage.size.width;

Now, using the above approach means that our image view will always have the exact same size as our image. This could mean that it stretches way outside the bounds of the screen or fills up just a tiny portion of the screen.

An alternative approach would be to use an aspect ratio constraint. Once again, start by giving your image view an aspect ratio constraint, relating its height to its width. Now go around and set up the rest of your autolayout constraints for the view. Perhaps you want the top left corner pinned to a specific location.

While you're doing this, you will also want to probably set some less than or equal to constraints for the image view's width and height. These constraints will make sure that no matter the size or shape of the image, the image view will be smaller than your specified size (and therefore stay on screen).

Once again, add an outlet for your aspect ratio constraint. We'll be modifying this each time we change the image view's image:

@property (nonatomic, weak) NSLayoutConstraint *imageRatio;

Now, instead of the constant property (we want to leave that at zero), we'll be modifying the multiplier property of the ratio constraint. Whether the width is on top or bottom depends exactly on how the constraint is hooked up, so it may require some trial and error. But the gist of it is, we want something like this:

self.imageRatio.multiplier = newImage.size.height / newImage.size.width;

(And again, you may have to flip height/width here.)

Community
  • 1
  • 1
nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • I don't resize the image before setting it in the imageView using the AspectFit. When I reassign the NSLayoutConstraint self.imageHeight.constant = newImage.size.height; imageHeight seems to become the original image height. Before reassigning imageWidth (the constraint) = 288, after imageWidth(constraint) = 1500. The constraints seem to be resizing to actual image, not the image displayed. Any thoughts? Thx for detailed answer! – leenyburger Jun 16 '15 at 19:38
  • Try the second approach I detailed using aspect ratio. – nhgrif Jun 16 '15 at 19:48