使用Aspect FitalignmentUIImageView

对于我的UIImageView,我select了Aspect Fit(InterfaceBuilder),但是如何改变垂直alignment呢?

[编辑 – 这个代码是从2011年有点模糊,除了我合并@ ArtOfWarefare的mods]

你不能这样做UIImageView。 我创build了一个包含UIImageView的简单的UIView子类MyImageView 。 下面的代码。

 // MyImageView.h #import <UIKit/UIKit.h> @interface MyImageView : UIView { UIImageView *_imageView; } @property (nonatomic, assign) UIImage *image; @end 

 // 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 

如果使用故事板,这可以通过约束来实现…

首先是具有期望的最终框架/约束的UIView。 将UIImageView添加到UIView。 将contentMode设置为Aspect Fill。 使UIImageView框架与图像的比例相同(这可避免以后出现任何Storyboard警告)。 使用标准约束将两侧固定到UIView。 使用标准约束将顶部或底部(取决于您想要alignment的位置)固定到UIView。 最后,在UIImageView中添加一个宽高比约束(确保比例为图像)。

尝试设置:

 imageView.contentMode = UIViewContentModeScaleAspectFit; imageView.clipsToBounds = YES; 

这对我有效。

我知道这是一个古老的线程,但我想我会分享我所做的,以便在界面生成器中轻松更改从图像视图的顶部到底部的剪辑区域,以防有人遇到同样的问题。 我有一个UIImageView,填充了我的ViewController的视图,并试图使顶部保持不变,与设备的屏幕大小无关。

  1. 我应用了视网膜4形状因子(编辑 – >应用视网膜4形态因子)。

  2. 我固定了高度和宽度。

现在,当屏幕更改大小时,UIImageView实际上是相同的大小,并且视图控制器只是剪辑屏幕上的内容。 帧原点保持在0,0,因此图像的右下angular被剪裁,而不是顶部。

希望这可以帮助。

感谢开发人员,我使用UIImageViewAligned来改变图像的alignment方式

UIImageViewAligned

你可以通过第一次缩放然后resize来完成。 这里要提到的是我受到身高的限制。 我的意思是,我不得不有34px高的形象,不pipe多宽。

因此,获取实际内容高度与视图高度(34像素)之间的比率,然后缩放宽度。

以下是我如何做到的:

 CGSize size = [imageView sizeThatFits:imageView.frame.size]; CGSize actualSize; actualSize.height = imageView.frame.size.height; actualSize.width = size.width / (1.0 * (size.height / imageView.frame.size.height)); CGRect frame = imageView.frame; frame.size = actualSize; [imageView setFrame:frame]; 

希望这可以帮助。

这有点棘手,因为如果你已经select了内容模式( .scaleAspectFit ),没有select设置进一步的alignment规则。

但是,这是一个解决方法:

首先需要通过计算尺寸来显式调整源图像的大小(如果是在带有contentMode = .scaleAspectFitUIImageView )。

 extension UIImage { func aspectFitImage(inRect rect: CGRect) -> UIImage? { let width = self.size.width let height = self.size.height let scaleFactor = width > height ? 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() } } 

然后你只需要通过传递你的imageView的框架来调用你的原始图像的这个函数,并将结果分配给你的UIImageView.image属性。 还要确保你在这里设置你的imageView所需的contentMode甚至在Interface Builder中 )!

 let image = UIImage(named: "MySourceImage") imageView.image = image?.aspectFitImage(inRect: imageView.frame) imageView.contentMode = .left 

我通过inheritanceUIImageView并重写setImage:方法解决了这个问题。 子类将首先存储原始值和大小的原始值,以便可以使用原始的大小作为边界框。

我将内容模式设置为UIViewContentModeAspectFit。 在setImage里面:我抓住图像宽高比,然后调整图像视图的大小以适应与图像相同的比例。 resize之后,我调整了框架属性,将图像视图设置在之前的相同位置,然后调用超级setImage :.

这导致了图像视图的框架被调整以准确地适合图像,所以方面匹配工作,并且图像视图框架属性在将图像视图放置在应该获得相同效果的地方进行繁重的工作。

以下是我使用的一些代码:

首先,我发现它通常是非常有用的,它是UIView上的一个类,它可以很容易地通过像left,right,top,bottom,width,height等属性在视图上设置框架属性。

的UIImageView + FrameAdditions

 @interface UIView (FrameAdditions) @property CGFloat left, right, top, bottom, width, height; @property CGPoint origin; @end @implementation UIView (FrameAdditions) - (CGFloat)left { return self.frame.origin.x; } - (void)setLeft:(CGFloat)left { self.frame = CGRectMake(left, self.frame.origin.y, self.frame.size.width, self.frame.size.height); } - (CGFloat)right { return self.frame.origin.x + self.frame.size.width; } - (void)setRight:(CGFloat)right { self.frame = CGRectMake(right - self.frame.size.width, self.frame.origin.y, self.frame.size.width, self.frame.size.height); } - (CGFloat)top { return self.frame.origin.y; } - (void)setTop:(CGFloat)top { self.frame = CGRectMake(self.frame.origin.x, top, self.frame.size.width, self.frame.size.height); } - (CGFloat)bottom { return self.frame.origin.y + self.frame.size.height; } - (void)setBottom:(CGFloat)bottom { self.frame = CGRectMake(self.frame.origin.x, bottom - self.frame.size.height, self.frame.size.width, self.frame.size.height); } - (CGFloat)width { return self.frame.size.width; } - (void)setWidth:(CGFloat)width { self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, self.frame.size.height); } - (CGFloat)height { return self.frame.size.height; } - (void)setHeight:(CGFloat)height { self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, height); } - (CGPoint)origin { return self.frame.origin; } - (void)setOrigin:(CGPoint)origin { self.frame = CGRectMake(origin.x, origin.y, self.frame.size.width, self.frame.size.height); } @end 

这是UIImageView的子类。 它没有得到充分的testing,但应该把想法交代。 这可以扩展为设置自己的新模式进行alignment。

BottomCenteredImageView

 @interface BottomCenteredImageView : UIImageView @end @interface BottomCenteredImageView() { CGFloat originalLeft; CGFloat originalBottom; CGFloat originalHeight; CGFloat originalWidth; } @end @implementation BottomCenteredImageView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if(self) { [self initialize]; } return self; } - (void)awakeFromNib { [self initialize]; } - (void)initialize { originalLeft = self.frame.origin.x; originalHeight = CGRectGetHeight(self.frame); originalWidth = CGRectGetWidth(self.frame); originalBottom = self.frame.origin.y + originalHeight; } - (void)setImage:(UIImage *)image { if(image) { self.width = originalWidth; self.height = originalHeight; self.left = originalLeft; self.bottom = originalBottom; float myWidthToHeightRatio = originalWidth/originalHeight; float imageWidthToHeightRatio = image.size.width/image.size.height; if(myWidthToHeightRatio >= imageWidthToHeightRatio) { // Calculate my new width CGFloat newWidth = self.height * imageWidthToHeightRatio; self.width = newWidth; self.left = originalLeft + (originalWidth - self.width)/2; self.bottom = originalBottom; } else { // Calculate my new height CGFloat newHeight = self.width / imageWidthToHeightRatio; self.height = newHeight; self.bottom = originalBottom; } self.contentMode = UIViewContentModeScaleAspectFit; [super setImage:image]; } else { [super setImage:image]; } } @end 

要调整缩放到适合的图像使用自动布局。 在UIImageView中进行缩放后适合右alignment的图像示例:

  1. 创build保存图像的UIImageView
  2. 为右,上,下,宽度添加自动约束
  3. 设置图像:
 myUIImageView.contentMode = .ScaleAspectFit myUIImageView.translatesAutoresizingMaskIntoConstraints = false myUIImageView.image = UIImage(named:"pizza.png") 

你的方面适合缩放的图像现在右alignment在UIImageView

 +----------------------------------+ | [IMAGE]| +----------------------------------+ 

将约束更改为在imageview中进行不同的alignment。