如何实现非矩形圆角效果?iOS图层遮罩问题求助
实现非矩形圆角遮罩效果的解决方案
问题描述
我想要实现非矩形圆角效果,最初尝试创建4个图层绘制路径制作圆角,但线条不够流畅所以放弃。之后用遮罩实现,实际效果和预期不符,附上我的代码,请问怎么实现预期的遮罩效果?
func makeGuideline() { let roundedRectangleLayer = CAShapeLayer() let roundedRectangleWidth = frame.width * 0.6 let roundedRectangleHeight = frame.height * 0.4 let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: (frame.width / 2 - roundedRectangleWidth / 2), y: (frame.height / 2 - roundedRectangleHeight / 2)), size: CGSize(width: roundedRectangleWidth, height: roundedRectangleHeight)), cornerRadius: 10) roundedRectangleLayer.path = path.cgPath roundedRectangleLayer.fillColor = .none roundedRectangleLayer.strokeColor = UIColor.red.cgColor roundedRectangleLayer.lineWidth = 1 let maskLayer = CAShapeLayer() let maskPath = UIBezierPath() let maskWidth = roundedRectangleWidth * 0.2 let maskHeight = roundedRectangleHeight * 0.3 maskPath.move(to: CGPoint(x: frame.width / 2 - maskWidth / 2, y: frame.height / 2 - roundedRectangleHeight / 2)) maskPath.addLine(to: CGPoint(x: frame.width / 2 - maskWidth / 2 + maskWidth, y: frame.height / 2 - roundedRectangleHeight / 2)) maskLayer.fillColor = .none maskLayer.path = maskPath.cgPath maskLayer.strokeColor = UIColor.blue.cgColor maskLayer.lineWidth = 1 maskLayer.fillRule = .evenOdd roundedRectangleLayer.mask = maskLayer layer.addSublayer(roundedRectangleLayer) }
问题分析
你的遮罩路径仅绘制了一条直线,且遮罩层未设置填充内容。CAShapeLayer作为遮罩时,只有填充区域会显示原图层内容,线条部分无法生效。结合预期效果(顶部中间带缺口的圆角矩形),直接绘制包含缺口的完整路径比使用遮罩更简单流畅。
正确实现方案
通过单一路径结合evenOdd填充规则,直接绘制带缺口的圆角矩形,代码如下:
func makeGuideline() { let targetLayer = CAShapeLayer() let rectWidth = frame.width * 0.6 let rectHeight = frame.height * 0.4 let rectOrigin = CGPoint(x: (frame.width - rectWidth)/2, y: (frame.height - rectHeight)/2) let baseRect = CGRect(origin: rectOrigin, size: CGSize(width: rectWidth, height: rectHeight)) let cornerRadius: CGFloat = 10 // 创建基础圆角矩形路径 let path = UIBezierPath(roundedRect: baseRect, cornerRadius: cornerRadius) // 添加顶部中间的缺口路径(可根据需求调整缺口尺寸和位置) let gapWidth = rectWidth * 0.2 let gapHeight = rectHeight * 0.3 let gapRect = CGRect( x: rectOrigin.x + (rectWidth - gapWidth)/2, y: rectOrigin.y - gapHeight/2, width: gapWidth, height: gapHeight ) path.append(UIBezierPath(rect: gapRect)) // 设置填充规则为evenOdd,实现缺口镂空效果 targetLayer.path = path.cgPath targetLayer.fillColor = UIColor.clear.cgColor targetLayer.strokeColor = UIColor.red.cgColor targetLayer.lineWidth = 1 targetLayer.fillRule = .evenOdd layer.addSublayer(targetLayer) }
关键说明
- 单图层绘制完整路径,避免多图层拼接导致的线条不流畅问题
evenOdd填充规则会让路径重叠区域镂空,刚好实现缺口效果- 若需要其他位置的缺口,只需调整
gapRect的坐标和尺寸即可
内容的提问来源于stack exchange,提问作者msgu
相关产品推荐
相关产品推荐

