看起来aspect fit
默认将图像与框架底部对齐。是否有一种方法可以在保持aspect fit
的情况下覆盖对齐方式?
** 编辑 **
这个问题先于自动布局。实际上,自动布局是在2012年WWDC上发布的,就在问这个问题的同一周。
看起来aspect fit
默认将图像与框架底部对齐。是否有一种方法可以在保持aspect fit
的情况下覆盖对齐方式?
** 编辑 **
这个问题先于自动布局。实际上,自动布局是在2012年WWDC上发布的,就在问这个问题的同一周。
简而言之,你不能使用UIImageView
来做到这一点。
一种解决方案是子类化一个包含UIImageView
的UIView
,并根据图片大小更改其框架。例如,你可以在这里找到一个版本(链接)。
typedef NS_OPTIONS(NSUInteger, AHTImageAlignmentMode) {
AHTImageAlignmentModeCenter = 0,
AHTImageAlignmentModeLeft = 1 << 0,
AHTImageAlignmentModeRight = 1 << 1,
AHTImageAlignmentModeTop = 1 << 2,
AHTImageAlignmentModeBottom = 1 << 3,
AHTImageAlignmentModeDefault = AHTImageAlignmentModeCenter,
};
- (void)updateImageViewContentsRect {
CGRect imageViewContentsRect = CGRectMake(0, 0, 1, 1);
if (self.image.size.height > 0 && self.bounds.size.height > 0) {
CGRect imageViewBounds = self.bounds;
CGSize imageSize = self.image.size;
CGFloat imageViewFactor = imageViewBounds.size.width / imageViewBounds.size.height;
CGFloat imageFactor = imageSize.width / imageSize.height;
if (imageFactor > imageViewFactor) {
//Image is wider than the view, so height will match
CGFloat scaledImageWidth = imageViewBounds.size.height * imageFactor;
CGFloat xOffset = 0.0;
if (BM_CONTAINS_BIT(self.alignmentMode, AHTImageAlignmentModeLeft)) {
xOffset = -(scaledImageWidth - imageViewBounds.size.width) / 2;
} else if (BM_CONTAINS_BIT(self.alignmentMode, AHTImageAlignmentModeRight)) {
xOffset = (scaledImageWidth - imageViewBounds.size.width) / 2;
}
imageViewContentsRect.origin.x = (xOffset / scaledImageWidth);
} else if (imageFactor < imageViewFactor) {
CGFloat scaledImageHeight = imageViewBounds.size.width / imageFactor;
CGFloat yOffset = 0.0;
if (BM_CONTAINS_BIT(self.alignmentMode, AHTImageAlignmentModeTop)) {
yOffset = -(scaledImageHeight - imageViewBounds.size.height) / 2;
} else if (BM_CONTAINS_BIT(self.alignmentMode, AHTImageAlignmentModeBottom)) {
yOffset = (scaledImageHeight - imageViewBounds.size.height) / 2;
}
imageViewContentsRect.origin.y = (yOffset / scaledImageHeight);
}
}
self.layer.contentsRect = imageViewContentsRect;
}
///Works perfectly with AspectFill. Note there's no protection for obscure issues like (say) scaledImageWidth is zero.
class AlignmentImageView: UIImageView {
enum HorizontalAlignment { case left, center, right }
enum VerticalAlignment { case top, center, bottom }
var horizontalAlignment: HorizontalAlignment = .center { didSet { updateContentsRect() } }
var verticalAlignment: VerticalAlignment = .center { didSet { updateContentsRect() } }
override var image: UIImage? { didSet { updateContentsRect() } }
override func layoutSubviews() {
super.layoutSubviews()
updateContentsRect()
}
private func updateContentsRect() {
var contentsRect = CGRect(origin: .zero, size: CGSize(width: 1, height: 1))
guard let imageSize = image?.size else {
layer.contentsRect = contentsRect
return
}
let viewBounds = bounds
let imageViewFactor = viewBounds.size.width / viewBounds.size.height
let imageFactor = imageSize.width / imageSize.height
if imageFactor > imageViewFactor {
// Image is wider than the view, so height will match
let scaledImageWidth = viewBounds.size.height * imageFactor
var xOffset: CGFloat = 0.0
if case .left = horizontalAlignment {
xOffset = -(scaledImageWidth - viewBounds.size.width) / 2
}
else if case .right = horizontalAlignment {
xOffset = (scaledImageWidth - viewBounds.size.width) / 2
}
contentsRect.origin.x = xOffset / scaledImageWidth
}
else {
let scaledImageHeight = viewBounds.size.width / imageFactor
var yOffset: CGFloat = 0.0
if case .top = verticalAlignment {
yOffset = -(scaledImageHeight - viewBounds.size.height) / 2
}
else if case .bottom = verticalAlignment {
yOffset = (scaledImageHeight - viewBounds.size.height) / 2
}
contentsRect.origin.y = yOffset / scaledImageHeight
}
layer.contentsRect = contentsRect
}
}
将UIImageView
底部的布局约束优先级设置为最低(即250),它将为您处理。
这将使图像填充宽度,并仅占用需要适应图像的高度 (就宽度而言)
Swift 4.2:
let image = UIImage(named: "my_image")!
let ratio = image.size.width / image.size.height
cardImageView.widthAnchor
.constraint(equalTo: cardImageView.heightAnchor, multiplier: ratio).isActive = true
我有类似的问题。 最简单的方法是创建自己的UIImageView子类。我为子类添加了3个属性,因此现在可以在不知道内部实现的情况下轻松使用:
@property (nonatomic) LDImageVerticalAlignment imageVerticalAlignment;
@property (nonatomic) LDImageHorizontalAlignment imageHorizontalAlignment;
@property (nonatomic) LDImageContentMode imageContentMode;
我在Interface Builder中通过设置UIImageView的高度约束来解决了这个问题,因为当图像大于屏幕尺寸时,图像会被“推”上去。
更具体地说,我通过高度约束将UIImageView设置为与其所在的视图相同的高度,然后在IB中使用间距约束来定位UIImageView。这样,UIImageView就具有了“Aspect Fit”的效果,同时仍然遵循我在IB中设置的顶部间距约束。
override var image: UIImage? {
didSet {
self.sizeToFit()
}
}