【问题标题】:Make an image view adjust its height to match the height of its image when the image is scaled down due to the content mode当图像由于内容模式而缩小时,使图像视图调整其高度以匹配其图像的高度
【发布时间】:2016-02-10 10:41:27
【问题描述】:

我有一个图像视图,它的左、右和上边缘被固定到它的超级视图,它的下边缘与下面的标签有一个固定的间距。它没有任何宽度或高度限制,因此它应该从其图像的固有尺寸中获取其高度。内容模式设置为Aspect Fit

如果图像的宽度小于或等于图像视图的宽度(情况 1 和 2,请参见下图),则此方法非常有用。但是,如果图像的宽度超过其包含的图像视图的宽度,我会遇到问题(案例 3):

图像按预期缩小,使其宽度与图像视图的宽度相匹配。 但图像视图不会相应地更新其高度,会在上方和下方留下空白。我知道图像视图仍然从图像的 original 高度获得它的高度。但是由于内容模式,图像的高度现在要小很多,我希望图像视图调整其高度以匹配图像的 实际高度。

我正在寻找一种适用于这三种情况的简洁解决方案,最好是一种适用于IB_DESIGNABLE 视图的解决方案。有什么想法吗?

案例一

内在宽度

案例 2

内在宽度 = 框架宽度

案例 3

内在宽度 > 框架宽度

【问题讨论】:

    标签: ios uiimageview autolayout interface-builder aspect-fit


    【解决方案1】:

    您可以通过以下方式在UIImageView 上创建扩展:

    extension UIImageView {
        @IBInspectable var shouldAdjustHeight: Bool {
            get {
                return self.frame.size.height == self.adjustedHeight;
            }
            set {
                if newValue {
                    if !shouldAdjustHeight {
                        let newHeight = self.adjustedHeight
    
                        // add constraint to adjust height
                        self.addConstraint(NSLayoutConstraint(
                            item:self, attribute:NSLayoutAttribute.Height,
                        relatedBy:NSLayoutRelation.Equal,
                        toItem:nil, attribute:NSLayoutAttribute.NotAnAttribute,
                        multiplier:0, constant:newHeight))
                }
            }
            else {
                let newHeight = self.adjustedHeight
                // create predicate to find the height constraint that we added
                let predicate = NSPredicate(format: "%K == %d && %K == %f", "firstAttribute", NSLayoutAttribute.Height.rawValue, "constant", newHeight)
                // remove constraint
                self.removeConstraints(self.constraints.filter{ predicate.evaluateWithObject($0) })
            }
        }
    }
    
    var adjustedHeight: CGFloat {
        let screenWidth = UIScreen.mainScreen().bounds.width
        let deviceScaleFactor = screenWidth/self.bounds.size.width
        return CGFloat(ceilf(Float(deviceScaleFactor * AVMakeRectWithAspectRatioInsideRect((self.image?.size)!, self.bounds).size.height))) // deviceScaleFactor multiplied with the image size for the frame
        // I am using size class in my XIB with value as (Any,Any) and I was not getting correct frame values for a particular device so I have used deviceScaleFactor.
        // You can modify above code to calculate newHeight as per your requirement
    }
    }
    

    添加上述扩展后,您可以在Interface-builder中设置属性,如下所示。

    设置此属性时,高度限制将添加到您的imageViewadjustedHeight 的计算在我的解决方案中可能不是很整洁,因此您可以进一步研究。

    【讨论】:

    • 感谢您的回答,@san。你能解释一下你想用deviceScaleFactor 实现什么吗?我看不出屏幕尺寸与问题有何关系。我也不想在 setter 方法内向视图添加约束,因为每次调用 setter 时都会创建一个新的约束。因此,如果我连续三次调用view.shouldAdjustHeight = true,我将为其添加三个(相等的)约束并且它们永远不会被删除,即使设置view.shouldAdjustHeight = false
    • @Mischa,我没有得到UIImageView 的正确帧,所以我使用了deviceScaleFactor。我不知道为什么我没有得到正确的帧值,这就是为什么我告诉你计算可能不是很整洁,但它适合你使用UIImageView 的方式。我已经更新了答案。如果高度已调整,则添加检查以不添加约束。还添加了代码以在您设置 imageView.shouldAdjustHeight = false 时删除约束
    猜你喜欢
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    相关资源
    最近更新 更多