You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现UIImageView用aspectToFil模式仅裁剪图片顶部显示底部内容?

解决方案:只显示长图的底部区域

嘿,这个场景我太熟了!contentMode = .bottom在图片尺寸远大于容器的时候确实不好使,aspectFill又会把上下都裁掉,只留中间。给你几个实用的解决办法,按需选就行:

方法1:用CALayer的contentsRect(最推荐)

contentsRect是基于单位坐标系(0到1的范围)来控制图层显示的图片区域,非常适合精准裁剪。核心思路是计算出要显示的底部区域在原图中的比例,然后设置给layer:

let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
imageView.image = yourLongVerticalImage
imageView.clipsToBounds = true

// 计算要显示的底部区域比例
guard let imgSize = imageView.image?.size else { return }
let viewHeight = imageView.bounds.height
// y轴偏移量:(原图高度 - 容器高度) / 原图高度,代表从顶部跳过多少比例的区域
let yOffset = (imgSize.height - viewHeight) / imgSize.height
// contentsRect的参数:x起始比例,y起始比例,宽度比例,高度比例
imageView.layer.contentsRect = CGRect(x: 0, y: yOffset, width: 1, height: viewHeight / imgSize.height)

这个方法代码简洁,性能也高,不需要自定义视图,大部分场景都能用。

方法2:自定义UIImageView重写绘制方法

如果需要更灵活的绘制控制,可以自定义一个UIImageView,直接在draw(_:)方法里绘制图片的底部区域:

class BottomCroppedImageView: UIImageView {
    override func draw(_ rect: CGRect) {
        guard let image = image else { 
            super.draw(rect)
            return 
        }
        
        // 计算原图中要截取的底部区域:高度和容器一致,y起始点是原图高度减去容器高度
        let sourceRect = CGRect(
            x: 0,
            y: image.size.height - rect.height,
            width: image.size.width,
            height: rect.height
        )
        
        // 把截取的区域绘制到当前视图的 bounds 里
        image.draw(in: rect, from: sourceRect, operation: .copy, fraction: 1.0)
    }
}

使用的时候直接创建这个自定义类的实例就行,适合需要叠加其他绘制逻辑的场景。

方法3:通过约束/frame偏移实现(AutoLayout友好)

如果用AutoLayout,可以通过调整图片的顶部约束,让图片的底部对齐容器底部,顶部超出容器范围,再配合clipsToBounds裁剪掉顶部:

let imageView = UIImageView()
imageView.image = yourLongVerticalImage
imageView.clipsToBounds = true
imageView.contentMode = .top // 让图片从顶部开始布局
imageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imageView)

guard let imgSize = imageView.image?.size else { return }
let viewHeight = view.bounds.height
// 计算图片顶部需要往上偏移的距离:原图高度 - 容器高度
let topOffset = imgSize.height - viewHeight

NSLayoutConstraint.activate([
    imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
    // 让图片顶部超出容器,偏移量为负的topOffset
    imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: -topOffset)
])

这个方法完全用AutoLayout实现,适合布局复杂的页面。

小提示

如果你的容器和图片宽高比一致(比如容器500×500,原图500×1000),方法1的contentsRect可以简化成CGRect(x:0, y:0.5, width:1, height:0.5),直接取原图的下半部分。

内容的提问来源于stack exchange,提问作者takutope

火山引擎 最新活动