如何实现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




