UIImage的方面配合和对齐顶部(UIImage aspect fit and align to

2019-06-25 12:44发布

它看起来像aspect fit对齐图像默认框架的底部。 有没有办法覆盖对齐,同时保持aspect fit完好?

**编辑**

这个问题早自动布局。 事实上,自动布局正在显露在2012年WWDC的同一个星期,这一问题被问

Answer 1:

总之,你不能用这样做UIImageView

一种解决方案是子类UIView含有UIImageView ,并根据图像的大小改变其帧。 例如,你可以找到一个版本在这里 。



Answer 2:

要做到这一点的方法是修改的UIImageView层的contentsRect。 从我的项目(子类的UIImageView)将下面的代码假定scaleToFill并抵消了图像,使得它对齐顶部,底部,左侧或右侧,而不是默认居中对齐。 对于aspectFit是将是一个类似的解决方案。

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;
}

斯威夫特版本

class AlignmentImageView: UIImageView {

    enum HorizontalAlignment {
        case left, center, right
    }

    enum VerticalAlignment {
        case top, center, bottom
    }


    // MARK: Properties

    var horizontalAlignment: HorizontalAlignment = .center
    var verticalAlignment: VerticalAlignment = .center


    // MARK: Overrides

    override var image: UIImage? {
        didSet {
            updateContentsRect()
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        updateContentsRect()
    }


    // MARK: Content layout

    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
    }

}


Answer 3:

刚刚成立的ImageView底部布局约束优先级到最低(即250),它会做的工作



Answer 4:

我有类似的问题。 最简单的方法是创建的UIImageView的自己的子类。 我想补充的子类3个属性所以现在可以使用伊斯利不知道内部实现:

@property (nonatomic) LDImageVerticalAlignment imageVerticalAlignment;
@property (nonatomic) LDImageHorizontalAlignment imageHorizontalAlignment;
@property (nonatomic) LDImageContentMode imageContentMode;

您可以点击此处查看: https://github.com/LucasssD/LDAlignmentImageView



Answer 5:

  1. 添加长宽比约束与图像比例。
  2. 别针式的UIImageView上下。
  3. 如果你想改变的UIImage动态记得更新的纵横比限制。


Answer 6:

我在Interface Builder解决这本身设置上的UIImageView的高度约束,因为图像将总是“推”了当图像比屏幕尺寸更大。

更具体而言,我设置的UIImageView是相同的高度查看它是在(经由高度约束),然后定位在IB间距约束的UIImageView。 这导致的UIImageView具有“方面适合”仍然尊重顶部间距约束我在IB设定。



Answer 7:

如果你能继承UIImageView ,那么你可以只覆盖image变种。

override var image: UIImage? {
    didSet {
        self.sizeToFit()
    }
}

在Objective-C,你可以通过重写setter方法做同样的事情。



文章来源: UIImage aspect fit and align to top