I want my UIImageView to grow or shrink depending on the size of what the actual image it\'s displaying is. But I want it to stay vertically centered and 10pts
Here is an AspectFit UIImageView-derived implementation that works with Auto Layout when only one dimension is constrained. The other one will be set automatically. It will keep image aspect ratio and doesn't add any margins around the image.
It's tweaked Objective-C implementation of @algal idea with the following differences:
priority = (UILayoutPriorityDefaultLow +
UILayoutPriorityFittingSizeLevel) / 2.0 which evaluates to 150
isn't enough to beat the priority of 1000 of the default image
content size constraint. So aspect constraint priority was increased
to 1000 as well.image setter could be called multiple times, so it's a good idea to not cause extra layout calculations here.required public init?(coder
aDecoder: NSCoder) and public override init(frame:CGRect), so
these two are taken out. They aren't overridden by UIImageView,
that's why there is no point of adding the aspect constraint until an image is set.AspectKeepUIImageView.h:
NS_ASSUME_NONNULL_BEGIN
@interface AspectKeepUIImageView : UIImageView
- (instancetype)initWithImage:(nullable UIImage *)image;
- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage;
@end
NS_ASSUME_NONNULL_END
AspectKeepUIImageView.m:
#import "AspectKeepUIImageView.h"
@implementation AspectKeepUIImageView
{
NSLayoutConstraint *_aspectContraint;
}
- (instancetype)initWithImage:(nullable UIImage *)image
{
self = [super initWithImage:image];
[self initInternal];
return self;
}
- (instancetype)initWithImage:(nullable UIImage *)image highlightedImage:(nullable UIImage *)highlightedImage
{
self = [super initWithImage:image highlightedImage:highlightedImage];
[self initInternal];
return self;
}
- (void)initInternal
{
self.contentMode = UIViewContentModeScaleAspectFit;
[self updateAspectConstraint];
}
- (void)setImage:(UIImage *)image
{
[super setImage:image];
[self updateAspectConstraint];
}
- (void)updateAspectConstraint
{
CGSize imageSize = self.image.size;
CGFloat aspectRatio = imageSize.height > 0.0f
? imageSize.width / imageSize.height
: 0.0f;
if (_aspectContraint.multiplier != aspectRatio)
{
[self removeConstraint:_aspectContraint];
_aspectContraint =
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeHeight
multiplier:aspectRatio
constant:0.f];
_aspectContraint.priority = UILayoutPriorityRequired;
[self addConstraint:_aspectContraint];
}
}
@end