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

后端 未结 8 489
花落未央
花落未央 2020-11-28 21:57

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

8条回答
  •  醉酒成梦
    2020-11-28 22:20

    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:

    • Expression 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.
    • it removes\re-adds the aspect ratio constraint only if necessary. Keep in mind that this is heavy operation so there is no need to do so if aspect ratio is the same. Moreover, image setter could be called multiple times, so it's a good idea to not cause extra layout calculations here.
    • not sure why we need to override 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
    

提交回复
热议问题