使用Aspect Fit对齐UIImageView

Rae*_*ime 74 iphone cocoa-touch interface-builder

对于我的UIImageView我选择了Aspect Fit(InterfaceBuilder),但是如何更改垂直对齐?

XJo*_*nes 40

[编辑 - 此代码从2011年开始有点发霉,除了我合并@ ArtOfWarefare的mods]

你不能用UIImageView这样做.我创建了一个MyImageView包含UIImageView 的简单UIView子类.代码如下.

// MyImageView.h
#import <UIKit/UIKit.h>

@interface MyImageView : UIView {
    UIImageView *_imageView;
}

@property (nonatomic, assign) UIImage *image;

@end
Run Code Online (Sandbox Code Playgroud)

// MyImageView.m

#import "MyImageView.h"

@implementation MyImageView

@dynamic image;

- (id)initWithCoder:(NSCoder*)coder
{
    self = [super initWithCoder:coder];
    if (self) {
        self.clipsToBounds = YES;
        _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        _imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self addSubview:_imageView];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.clipsToBounds = YES;
        _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        _imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self addSubview:_imageView];
    }
    return self;
}

- (id)initWithImage:(UIImage *)anImage
{
    self = [self initWithFrame:CGRectZero];
    if (self) {
        _imageView.image = anImage;
        [_imageView sizeToFit];

        // initialize frame to be same size as imageView
        self.frame = _imageView.bounds;        
    }
    return self;
}

// Delete this function if you're using ARC
- (void)dealloc
{
    [_imageView release];
    [super dealloc];
}

- (UIImage *)image
{
    return _imageView.image;
}

- (void)setImage:(UIImage *)anImage
{
    _imageView.image = anImage;
    [self setNeedsLayout];
}

- (void)layoutSubviews
{
    if (!self.image) return;

    // compute scale factor for imageView
    CGFloat widthScaleFactor = CGRectGetWidth(self.bounds) / self.image.size.width;
    CGFloat heightScaleFactor = CGRectGetHeight(self.bounds) / self.image.size.height;

    CGFloat imageViewXOrigin = 0;
    CGFloat imageViewYOrigin = 0;
    CGFloat imageViewWidth;
    CGFloat imageViewHeight;


    // if image is narrow and tall, scale to width and align vertically to the top
    if (widthScaleFactor > heightScaleFactor) {
        imageViewWidth = self.image.size.width * widthScaleFactor;
        imageViewHeight = self.image.size.height * widthScaleFactor;
    }

    // else if image is wide and short, scale to height and align horizontally centered
    else {
        imageViewWidth = self.image.size.width * heightScaleFactor;
        imageViewHeight = self.image.size.height * heightScaleFactor;
        imageViewXOrigin = - (imageViewWidth - CGRectGetWidth(self.bounds))/2;
    }

    _imageView.frame = CGRectMake(imageViewXOrigin,
                                  imageViewYOrigin,
                                  imageViewWidth,
                                  imageViewHeight);
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self setNeedsLayout];
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 我必须做的两件小事情:1 - 我实现了`initWithCoder`(我基本上复制了你的`initWithFrame`但用`[super initWithCoder:]`替换了``super initWithFrame:]`)和2 - I添加在一行`if(!self.image)return;`到`layoutSubviews`,这样如果在调用图像时没有分配图像,它就不会因无效几何图形而崩溃.通过这两个小变化,它的工作效果令人惊讶. (3认同)

Mic*_*att 31

如果使用Storyboard,这可以通过约束来实现......

首先是具有所需最终帧/约束的UIView.将UIImageView添加到UIView.将contentMode设置为Aspect Fill.使UIImageView框架与图像的比例相同(这可以避免以后的任何Storyboard警告).使用标准约束将边固定到UIView.使用标准约束将顶部或底部(取决于您想要对齐的位置)固定到UIView.最后将一个宽高比约束添加到UIImageView(确保比率作为图像).

  • 我用@MichaelPlatt解决方案创建了UIImageView扩展.https://gist.github.com/megimix/d0bbea45bd3e1e4d615fbd5c30b54da7 (3认同)
  • 我也已经实现了,它可以工作。由于该解决方案描述了自动布局约束设置,因此似乎令人困惑。对于其他开发人员,我的实现使用从Web加载的图像,因此我必须根据图像的宽度/高度以编程方式删除并重新添加UIImageView宽高比约束。 (2认同)

cho*_*fie 11

这有点棘手,因为如果您已经选择了内容模式(.scaleAspectFit),则无法设置更多对齐规则.

但这是一个解决方法:

首先需要通过计算尺寸(如果它在UIImageViewwith中contentMode = .scaleAspectFit)明确地调整源图像的大小.

extension UIImage {

    func aspectFitImage(inRect rect: CGRect) -> UIImage? {
        let width = self.size.width
        let height = self.size.height
        let aspectWidth = rect.width / width
        let aspectHeight = rect.height / height
        let scaleFactor = aspectWidth > aspectHeight ? rect.size.height / height : rect.size.width / width

        UIGraphicsBeginImageContextWithOptions(CGSize(width: width * scaleFactor, height: height * scaleFactor), false, 0.0)
        self.draw(in: CGRect(x: 0.0, y: 0.0, width: width * scaleFactor, height: height * scaleFactor))

        defer {
            UIGraphicsEndImageContext()
        }

        return UIGraphicsGetImageFromCurrentImageContext()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您只需要通过传递imageView的框架在原始图像上调用此函数,并将结果分配给您的UIImageView.image属性.另外,请确保contentMode在此处设置imageView (甚至在Interface Builder中)!

let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left
Run Code Online (Sandbox Code Playgroud)


Jon*_*ina 8

尝试设置:

imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;
Run Code Online (Sandbox Code Playgroud)

这对我有用.