对于我的UIImageView,我选择Aspect Fit(InterfaceBuilder),但是如何更改垂直对齐方式?
对于我的UIImageView,我选择Aspect Fit(InterfaceBuilder),但是如何更改垂直对齐方式?
Answers:
[编辑-此代码从2011年开始有点发霉,除了我之外,我都加入了@ArtOfWarefare的mods]
使用UIImageView无法执行此操作。我创建了一个简单的UIView子类MyImageView
,其中包含UIImageView。下面的代码。
// 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
initWithCoder
(我基本上是复制你的initWithFrame
,但换成了[super initWithFrame:]
用[super initWithCoder:]
)和2 -我在一条线上加入if (!self.image) return;
到layoutSubviews
这样它不会与无效的几何体崩溃,如果图像ISN” t在调用时分配。通过这两个小的更改,它的运行效果惊人。
dealloc
必须删除方法。
如果使用情节提要,则可以在限制条件下实现...
首先,UIView具有所需的最终框架/约束。将UIImageView添加到UIView。将contentMode设置为Aspect Fill。使UIImageView框架与图像具有相同的比率(这避免了以后出现任何Storyboard警告)。使用标准约束将侧面固定到UIView。使用标准约束将顶部或底部(取决于您希望对齐的位置)固定到UIView。最后,将长宽比约束添加到UIImageView(确保将长宽比作为图像)。
这有点棘手,因为如果您已经选择了内容模式(.scaleAspectFit
),则无法设置进一步的对齐规则。
但这是一种解决方法:
首先,需要通过计算尺寸来显式地调整源图像的大小(如果它在UIImageView
with中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()
}
}
然后,您只需通过传递imageView的框架并将结果分配给您的UIImageView.image
属性,即可在原始图像上调用此函数。另外,请确保contentMode
在此处(甚至在Interface Builder中)设置所需的imageView !
let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left
由于开发人员,我使用UIImageViewAligned来更改图像的对齐方式
您可以先缩放然后再调整大小。这里要提到的是我受身高限制。我的意思是,无论宽度如何,我都必须拥有34px高的图像。
因此,获取实际内容高度与视图高度(34 px)之间的比率,然后再缩放宽度。
这是我的做法:
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];
希望这可以帮助。
我想到了以下解决方案:
UIImageView
内容模式设置为top
:imageView.contentMode = .top
要加载和调整图像大小,我使用Kingfisher:
let size = imageView.bounds.size
let processor = ResizingImageProcessor(referenceSize: size, mode: .aspectFit)
imageView.kf.setImage(with: URL(string: imageUrl), options: [.processor(processor), .scaleFactor(UIScreen.main.scale)])
我通过子类化UIImageView并重写setImage:方法解决了此问题。子类将首先存储其原始值以作为原点和大小,以便可以将原始设置的大小用作边界框。
我将内容模式设置为UIViewContentModeAspectFit。在setImage内部:我抓取图像的宽高比,然后调整图像视图的大小以适合与图像相同的比例。调整大小后,我调整了帧属性以将图像视图设置为与以前相同的位置,然后调用了超级setImage:。
这会导致对图像视图的帧进行调整以完全适合图像,因此,宽高比拟合工作正常,并且图像视图帧的属性在将图像视图放置在应具有相同效果的位置上起了很大的作用。
这是我使用的一些代码:
首先,我发现它在总体上很有用,它是UIView上的一个类别,它可以通过诸如左,右,上,下,宽度,高度等属性轻松在视图上设置框架属性。
@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的子类。它尚未经过全面测试,但应该可以使您理解。可以将其扩展为设置自己的新对齐方式。
@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
如果您需要实现AspectFit并消除空白
不要忘记从情节提要中删除imageview的宽度限制并享受
class SelfSizedImageView:UIImageView {
override func layoutSubviews() {
super.layoutSubviews()
guard let imageSize = image?.size else {
return
}
let viewBounds = bounds
let imageFactor = imageSize.width / imageSize.height
let newWidth = viewBounds.height * imageFactor
let myWidthConstraint = self.constraints.first(where: { $0.firstAttribute == .width })
myWidthConstraint?.constant = min(newWidth, UIScreen.main.bounds.width / 3)
layoutIfNeeded()
}}
要对齐缩放比例以适合图像,请使用自动布局。在UIImageView中缩放以适合后的示例右对齐图像:
myUIImageView.contentMode = .ScaleAspectFit
myUIImageView.translatesAutoresizingMaskIntoConstraints = false
myUIImageView.image = UIImage(named:"pizza.png")
您的宽高比缩放图像现在在UIImageView中右对齐
+----------------------------------+
| [IMAGE]|
+----------------------------------+
更改约束以在imageview中进行不同的对齐。