对于我的UIImageView
,我选择了Aspect Fit
(在InterfaceBuilder中),但是如何更改垂直对齐方式呢?
对于我的UIImageView
,我选择了Aspect Fit
(在InterfaceBuilder中),但是如何更改垂直对齐方式呢?
[编辑 - 这段代码有些陈旧,因为它是2011年的,但我已经合并了@ArtOfWarefare的修改]
你不能使用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- 在 layoutSubviews
中添加了一行代码 if (!self.image) return;
,这样在调用时如果没有分配图像,它就不会因为无效的几何形状而崩溃。通过这两个小改动,它能够惊人地工作。 - ArtOfWarfaredealloc
方法。 - Raptor由于已选择了内容模式(.scaleAspectFit
),因此没有设置进一步对齐规则的选项,这有点棘手。
但是,这里有一个解决方法:
首先,需要通过计算尺寸(如果它在具有contentMode = .scaleAspectFit
的UIImageView
中)来明确调整源图像的大小。
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
属性。另外,请确保在此处设置您的imageView所需的contentMode
(甚至可以在Interface Builder中设置)!
let image = UIImage(named: "MySourceImage")
imageView.image = image?.aspectFitImage(inRect: imageView.frame)
imageView.contentMode = .left
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES;
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)])
如果您需要实现aspectFit并去除空白区域
不要忘记从storyboard中删除图像视图的宽度约束,然后享受它吧
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()
}}
你可以先进行缩放,然后再调整大小。
需要注意的是,我是按照高度来设定的。也就是说,无论宽度如何,我都必须将图像的高度设置为34像素。
因此,需要获取实际内容高度与视图高度(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];
感谢 @michael-platt
imageView.contentMode = .scaleAspectFit
let width = Layout.height * image.size.width / image.size.height
imageView.widthAnchor.constraint(equalToConstant: width).isActive = true
func setupImageView(for image: UIImage) {
let imageView = UIImageView()
imageView.backgroundColor = .orange
//Content mode
imageView.contentMode = .scaleAspectFill
view.addSubview(imageView)
//Constraints
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
//Feel free to set the height to any value
imageView.heightAnchor.constraint(equalToConstant: 150).isActive = true
//ImageView width calculation
let width = Layout.height * image.size.width / image.size.height
imageView.widthAnchor.constraint(equalToConstant: width).isActive = true
}