【问题标题】:Is it possible to use the aspect fill content mode combined with the top content mode in UIImageView?是否可以在 UIImageView 中使用方面填充内容模式与顶部内容模式相结合?
【发布时间】:2017-12-19 10:08:25
【问题描述】:

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

这是我设置为宽高比填充的图像视图:

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

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

【问题讨论】:

  • 定义“合并”。
  • 我的意思是我想在我的 ImageView 中同时使用这两种内容模式。有可能吗?
  • @V-Dev。您只想实现图像的顶部或中心裁剪
  • 我想从图像顶部填充 AspectFill。如您所见,我的 AspectFill Cut 图像头部。
  • 你的意思是同时有两种内容模式???

标签: ios image


【解决方案1】:

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

您应该调整图像的大小,使其具有您的图像视图的宽度,但要保持其纵横比。之后,将图像视图的内容模式设置为.top 并为其启用剪切到边界。

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

func setImageView() {
    imageView.contentMode = .top
    imageView.clipsToBounds = true

    let image = <custom image>
    imageView.image = image.resizeTopAlignedToFill(newWidth: imageView.frame.width)
}

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

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

【讨论】:

  • 这里的let scale 未使用
  • 这不保持图像的纵横比,高度保持不变,宽度更新,因此图像被压扁/拉伸。
  • @JamesP 你说得对,感谢您的通知,newHeight 的计算丢失了。我更新了我的代码。
【解决方案2】:

这是我的解决方案。首先,将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)

【讨论】:

    【解决方案3】:

    接受的答案是缩小图像,从而降低@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)
    

    【讨论】:

    • 我刚刚测试了这段代码,它错误地缩放了图像,所以看起来像是被拉伸了。
    • 否则,感谢您提供有关不正确的 2x 和 3x 缩放的信息,我会更新我的答案!
    【解决方案4】:

    试试这个:

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

    【讨论】:

      【解决方案5】:

      作为性能问题,我建议将具有完整图像大小/纵横比的 UIImageView 放入具有 clipsToBounds 设置为 true 的 ContainerView。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-26
        • 1970-01-01
        • 2012-12-17
        • 1970-01-01
        • 2017-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多