iOS Swift中如何为任意尺寸UIImage设置固定值圆角
问题原因
当前实现直接在原图的实际像素尺寸上添加圆角,而UIImageView使用了scaleAspectFit显示模式,不同尺寸的原图会被等比例缩放至适配ImageView边界,添加在原图上的圆角也会跟随整体缩放,最终显示的圆角大小自然不一致:
- 4000×4000的大图添加25单位圆角后,若被缩小8倍显示,圆角也会同步缩小至3~5单位,和你观测的效果一致
- 500×500的小图添加25单位圆角后,若被放大2倍显示,圆角也会同步放大至50单位,和你观测的效果一致
修复方案
核心逻辑是保证圆角在最终显示到屏幕的图片尺寸上添加,避免后续缩放影响圆角大小。你可以先把原图等比例缩放到适配UIImageView的显示尺寸,再添加25pt圆角,还能同时降低大图片的内存占用。
修改后的完整代码如下:
class TheCountdownDetails: UIViewController { let photoPreview = UIImageView() // 标记图片是否已设置,避免viewDidLayoutSubviews多次调用重复生成图片 private var hasLoadedImage = false override func viewDidLoad() { super.viewDidLoad() photoPreview.translatesAutoresizingMaskIntoConstraints = false photoPreview.contentMode = .scaleAspectFit view.addSubview(photoPreview) photoPreview.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true photoPreview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true photoPreview.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true photoPreview.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() guard !hasLoadedImage else { return } hasLoadedImage = true // 先获取ImageView的实际显示尺寸作为缩放目标 let displaySize = photoPreview.bounds.size // 先缩放图片,再加圆角 let targetImage = UIImage(named: "demo")? .scaledToFit(targetSize: displaySize)? .withRoundedCorners(radius: 25) photoPreview.image = targetImage } } extension UIImage { /// 等比例缩放图片至适配目标尺寸 func scaledToFit(targetSize: CGSize) -> UIImage? { let widthRatio = targetSize.width / size.width let heightRatio = targetSize.height / size.height let scale = min(widthRatio, heightRatio) let scaledSize = CGSize(width: size.width * scale, height: size.height * scale) UIGraphicsBeginImageContextWithOptions(scaledSize, false, UIScreen.main.scale) draw(in: CGRect(origin: .zero, size: scaledSize)) let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result } /// 给当前图片添加圆角 public func withRoundedCorners(radius: CGFloat? = nil) -> UIImage? { let maxRadius = min(size.width, size.height) / 2 let cornerRadius: CGFloat if let radius = radius, radius > 0 && radius <= maxRadius { cornerRadius = radius } else { cornerRadius = maxRadius } UIGraphicsBeginImageContextWithOptions(size, false, scale) let rect = CGRect(origin: .zero, size: size) UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).addClip() draw(in: rect) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return image } }
可选方案(保留原图分辨率)
如果你需要保留原图的高清分辨率,不想提前缩放,也可以根据图片的缩放比例动态换算原图需要的圆角大小:原图圆角 = 目标显示圆角 / 图片在ImageView中的缩放比例
换算后再调用原有圆角方法即可,也能保证最终显示的圆角大小固定为25pt。
内容的提问来源于stack exchange,提问作者Travgalax
相关产品推荐
相关产品推荐

