Swift中如何为添加到CGMutablePath的圆角矩形设置边框?
解决方案
问题根因
你之前将负责镂空的路径层设置为了视图的mask,mask仅控制视图的可见区域,镂空位置的视图本身是完全透明的,你在该视图上添加的所有子层/内容在镂空区域都会被mask隐藏,这是边框无法显示的核心原因。
优化实现方案
放弃使用mask实现镂空,直接通过CAShapeLayer的填充规则实现带镂空的半透明遮罩,同时新增独立的描边层绘制红色边框,且将layer更新逻辑移到layoutSubviews避免重复绘制:
- 声明专用属性存储遮罩填充层和边框层
- 初始化时配置两个layer的基础样式并添加到视图层级
- 动态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
相关产品推荐
相关产品推荐

