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

Swift中如何为添加到CGMutablePath的圆角矩形设置边框?

解决方案

问题根因

你之前将负责镂空的路径层设置为了视图的mask,mask仅控制视图的可见区域,镂空位置的视图本身是完全透明的,你在该视图上添加的所有子层/内容在镂空区域都会被mask隐藏,这是边框无法显示的核心原因。

优化实现方案

放弃使用mask实现镂空,直接通过CAShapeLayer的填充规则实现带镂空的半透明遮罩,同时新增独立的描边层绘制红色边框,且将layer更新逻辑移到layoutSubviews避免重复绘制:

  1. 声明专用属性存储遮罩填充层和边框层
  2. 初始化时配置两个layer的基础样式并添加到视图层级
  3. 动态frame变化时同步更新两个layer的路径

完整代码示例

class HollowMaskView: UIView {
    // 动态变化的镂空frame
    var changingFrame: CGRect? {
        didSet {
            updateLayerPaths()
        }
    }
    
    // 遮罩填充层
    private let maskFillLayer = CAShapeLayer()
    // 镂空边框层
    private let strokeLayer = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayers()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupLayers()
    }
    
    private func setupLayers() {
        backgroundColor = .clear
        
        // 配置填充层
        maskFillLayer.fillColor = UIColor.blue.cgColor
        maskFillLayer.fillRule = .evenOdd
        layer.addSublayer(maskFillLayer)
        
        // 配置边框层
        strokeLayer.fillColor = UIColor.clear.cgColor
        strokeLayer.strokeColor = UIColor.red.cgColor
        strokeLayer.lineWidth = 2 // 可自行调整边框宽度
        layer.addSublayer(strokeLayer)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        updateLayerPaths()
    }
    
    private func updateLayerPaths() {
        // 更新填充层路径(实现镂空效果)
        let fillPath = CGMutablePath()
        if let hollowFrame = changingFrame {
            fillPath.addRoundedRect(in: hollowFrame, cornerWidth: 16, cornerHeight: 16)
        }
        fillPath.addRect(bounds)
        maskFillLayer.path = fillPath
        maskFillLayer.frame = bounds
        
        // 更新边框层路径
        let strokePath = CGMutablePath()
        if let hollowFrame = changingFrame {
            // 如果需要边框完全内嵌在镂空区域,可调整frame:hollowFrame.insetBy(dx: 1, dy: 1)
            strokePath.addRoundedRect(in: hollowFrame, cornerWidth: 16, cornerHeight: 16)
        }
        strokeLayer.path = strokePath
        strokeLayer.frame = bounds
    }
}

额外说明

  • 原代码中的draw(_ rect:)方法可以完全删除,无需额外实现,基于layer的实现性能更优
  • 如果需要调整边框的显示位置(内描边/外描边),可以通过调整圆角矩形的inset和lineWidth实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 14:15:08