是否可以在UIImageView中使用方面填充内容模式与顶级内容模式相结合?

时间:2017-12-19 10:08:26

标签: ios image

对于UIImageView,我使用的是方面填充内容模式。没关系,但对于某些图片,它会从顶部剪切,因为我使用了clipsToBounds = true。所以这就是我想要的:我想让两个过滤器同时处于活动状态,例如:

这是我设置为纵横填充的图像视图:

image view with the aspect fill content mode

...以及我使用contentMode = .top设置的图片视图:

image view with the top content mode

所以我想合并这两种内容模式。可能吗?提前谢谢。

5 个答案:

答案 0 :(得分:7)

更新:现在可以正确处理设备缩放,感谢budidino

您应该调整图像的大小,使其具有图像视图的宽度,但保持其纵横比。之后,将图片视图的内容模式设置为.top,并启用剪裁以限制它。

resizeTopAlignedToFill函数是this answer的修改版本。

func setImageView() {
    imageView.contentMode = .top
    imageView.clipsToBounds = true
    imageView.image = UIImage(named: "portrait").resizeTopAlignedToFill(newWidth: imageView.frame.width)
}

extension UIImage {
    func resizeTopAlignedToFill(newWidth: CGFloat) -> UIImage? {
        let newHeight = size.height

        let newSize = CGSize(width: newWidth, height: newHeight)

        UIGraphicsBeginImageContextWithOptions(newSize, false, UIScreen.main.scale)
        draw(in: CGRect(origin: .zero, size: newSize))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }
}

答案 1 :(得分:3)

试试这个:

imageView.contentMode = UIViewContentModeTop;
imageView.image = [UIImage imageWithCGImage:image.CGImage scale:image.size.width / imageView.frame.size.width orientation:UIImageOrientationUp];

答案 2 :(得分:1)

可接受的答案是按比例缩小图像,因此降低了@ 2x和@ 3x设备的质量。这样可以产生相同的结果,并具有更好的图像质量:

extension UIImage {
  func resizeTopAlignedToFill(containerSize: CGSize) -> UIImage? {
    let scaleTarget = containerSize.height / containerSize.width
    let scaleOriginal = size.height / size.width

    if scaleOriginal <= scaleTarget { return self }

    let newHeight = size.width * scaleTarget
    let newSize = CGSize(width: size.width, height: newHeight)

    UIGraphicsBeginImageContextWithOptions(newSize, false, scale)
    self.draw(in: CGRect(origin: .zero, size: newSize))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
  }
}

然后只使用它

imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.image = UIImage(named: "portrait").resizeTopAlignedToFill(containerSize: imageView.frame.size)

答案 3 :(得分:0)

这是我的解决方案。首先,将comtentMode设置为top,然后调整图像大小

func resize(toWidth scaledToWidth: CGFloat) -> UIImage {
        let image = self
        let oldWidth = image.size.width
        let scaleFactor = scaledToWidth / oldWidth
        let newHeight = image.size.height * scaleFactor
        let newWidth = oldWidth * scaleFactor
        let scaledSize = CGSize(width:newWidth, height:newHeight)
        UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0)
        image.draw(in: CGRect(x: 0, y: 0, width: scaledSize.width, height: scaledSize.height))
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return scaledImage!
    }

imageView.contentMode = .top
imageView.image = imageView.resize(toWidth:imageView.frame.width)

答案 4 :(得分:0)

出于性能方面的考虑,我建议将具有完整图像尺寸/长宽比的UIImageView放入一个将clipsToBounds设置为true的ContainerView中。