如何为contentMode设为scaleAspectFit的UIImageView添加cornerRadius
解决UIImageView使用scaleAspectFit时圆角不生效的问题
问题原因
当UIImageView的contentMode设为.scaleAspectFit时,图像会保持原始比例完整显示在视图内部,不会超出视图边界。此时clipsToBounds = true只会裁剪视图外部的内容,对视图内部的图像没有裁剪作用——图像本身仍是直角矩形,视图的圆角只会作用于空白区域(如果视图背景透明,就看不到圆角效果)。而.scaleAspectFill模式下图像会填满视图并超出边界,clipsToBounds会裁剪超出部分(包括圆角区域),所以圆角生效。
解决方案1:使用容器视图包裹(推荐)
给UIImageView套一层容器视图,将圆角和裁剪属性设置在容器上,UIImageView保持.scaleAspectFit模式即可。
修改后的代码:
// 创建容器视图,负责实现圆角裁剪 private let imageContainerView: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.clipsToBounds = true view.layer.cornerRadius = 30 return view }() private let imageView: UIImageView = { let image = UIImageView() image.translatesAutoresizingMaskIntoConstraints = false image.image = UIImage(named: "105") image.contentMode = .scaleAspectFit return image }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground setUpConstraints() } private func setUpConstraints(){ view.addSubview(btnClose) view.addSubview(lblRateIT) view.addSubview(lblLoveIT) view.addSubview(redBottomView) // 先添加容器视图到父视图,再将imageView加入容器 view.addSubview(imageContainerView) imageContainerView.addSubview(imageView) NSLayoutConstraint.activate([ // 容器视图沿用原imageView的布局约束 imageContainerView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50), imageContainerView.topAnchor.constraint(equalTo: lblLoveIT.bottomAnchor, constant: 20), imageContainerView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50), imageContainerView.bottomAnchor.constraint(equalTo: redBottomView.topAnchor, constant: -20), // imageView填满容器视图 imageView.leadingAnchor.constraint(equalTo: imageContainerView.leadingAnchor), imageView.topAnchor.constraint(equalTo: imageContainerView.topAnchor), imageView.trailingAnchor.constraint(equalTo: imageContainerView.trailingAnchor), imageView.bottomAnchor.constraint(equalTo: imageContainerView.bottomAnchor) ]) }
解决方案2:直接给UIImage添加圆角
通过图形上下文直接将原图像处理成圆角图片,再赋值给UIImageView。
首先添加UIImage扩展:
extension UIImage { func roundedImage(withRadius radius: CGFloat) -> UIImage? { let rect = CGRect(origin: .zero, size: self.size) UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale) let path = UIBezierPath(roundedRect: rect, cornerRadius: radius) path.addClip() self.draw(in: rect) let roundedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return roundedImage } }
然后修改imageView的初始化代码:
private let imageView: UIImageView = { let image = UIImageView() image.translatesAutoresizingMaskIntoConstraints = false image.contentMode = .scaleAspectFit // 加载并处理圆角图片 if let originalImage = UIImage(named: "105") { image.image = originalImage.roundedImage(withRadius: 30) } return image }()
如果需要根据UIImageView的实际尺寸调整圆角半径,可在viewDidLayoutSubviews中处理:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard let originalImage = UIImage(named: "105") else { return } // 确保圆角半径不超过视图短边的一半 let radius = min(imageView.bounds.width, imageView.bounds.height) / 2 > 30 ? 30 : min(imageView.bounds.width, imageView.bounds.height) / 2 imageView.image = originalImage.roundedImage(withRadius: radius) }
解决方案3:使用CAShapeLayer作为mask
给UIImageView的layer添加一个圆角形状的mask,强制裁剪图像内容。
在viewDidLayoutSubviews中设置mask:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let maskPath = UIBezierPath(roundedRect: imageView.bounds, cornerRadius: 30) let maskLayer = CAShapeLayer() maskLayer.path = maskPath.cgPath imageView.layer.mask = maskLayer }
内容的提问来源于stack exchange,提问作者chevi99
相关产品推荐
相关产品推荐

