You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 19:36:01