UIImageView: combine UIViewContentModeScaleAspectFit and UIViewContentModeBottom
Is there a way to avoid image stretching in an UIImageView
and aligning it to the bottom at the same time? Basically I want to obtain what would happen if it was possible to combine the UIViewContentModeScaleAspectF开发者_如何学Pythonit
and UIViewContentModeBottom
contentMode
s.
Found the solution on my own. This code resizes the UIImageView
to its image
's size, and moves it at the bottom of its superview.
CGSize initialImageSize = imageView.size;
CGSize imageSize = imageView.image.size;
CGFloat aspectRatio = imageSize.width / imageSize.height;
CGRect imageFrame = imageView.frame;
if (initialImageSize.width / aspectRatio <= initialImageSize.height) {
imageFrame.size.width = initialImageSize.width;
imageFrame.size.height = imageFrame.size.width / aspectRatio;
} else {
imageFrame.size.height = initialImageSize.height;
imageFrame.size.width = imageFrame.size.height * aspectRatio;
}
CGRect parentFrame = imageView.superview.frame;
imageFrame.origin.y = (parentFrame.origin.y + parentFrame.size.height) - imageFrame.size.height;
imageView.frame = imageFrame;
Constraint based approach
You'll want to constrain the left
, right
, and bottom
sides of the UIImageView
while ensuring the ratio of the size is the same as the UIImage
that it's displaying.
UIImage *image; // allocate image object here
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
[parent addSubview:imageView]; // add imageView to proper view with addSubview: here
UIView *superview = imageView.superview; // match width and bottom of self.superview
CGFloat ratio = image.size.width / image.size.height;
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1.f constant:0.f];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1.f constant:0.f];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:imageView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1.f constant:0.f];
NSLayoutConstraint *ratioConstraint = [NSLayoutConstraint constraintWithItem:imageView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:imageView
attribute:NSLayoutAttributeHeight
multiplier:ratio
constant:1.f];
[imageView addConstraint:ratioConstraint];
[superview addConstraints:@[leftConstraint, bottomConstraint, rightConstraint]];
This will emulate a combination of UIViewContentModeScaleAspectFit
and UIViewContentModeBottom
but will resize the height of the UIImageView
as well.
My solution:
float newwidth;
float newheight;
if (image.size.height>=image.size.width){
newheight=imageview.frame.size.height;
newwidth=(image.size.width/image.size.height)*newheight;
if(newwidth>imageview.frame.size.width){
float diff=imageview.frame.size.width-newwidth;
newheight=newheight+diff/newheight*newheight;
newwidth=imageview.frame.size.width;
}
}
else{
newwidth=imageview.frame.size.width;
newheight=(image.size.height/image.size.width)*newwidth;
if(newheight>imageview.frame.size.height){
float diff=imageview.frame.size.height-newheight;
newwidth=newwidth+diff/newwidth*newwidth;
newheight=imageview.frame.size.height;
}
}
I have found a much easier way to do it.
imageView.contentMode = .Bottom
imageView.clipToBounds = true
This will prevent the image from resizing no matter what frame it is bounded in. And the clipToBounds part is important because it prevents the non resized image from going outside the imageView bounds.
Late to the party, but a simple solution. On the UIImageView:
- Use the contentMode property to position the image. (in the current case UIView.ContentMode.bottom)
- Use the contentScaleFactor property of the UIImageView to scale the image in the content view.
This will maintain the aspect ratio, just calculate the scale you need. For scaleAspectFit:
yourImageView.contentMode = UIView.ContentMode.bottom
let relWidthScale = yourImage.size.width/yourImageView.frame.width
let relHeightScale = yourImage.size.height/yourImageView.frame.height
yourImageView.contentScaleFactor = min(relWidthScale,relHeightScale)
If the UIImageView changes size, you can update the scale by adding an observer to the bounds property of the UIImageView or its container.
精彩评论