先上图后扯淡
1.完整代码
func popLayer(with frame: CGRect) -> CAShapeLayer {
// 凸出的高度
let bulge: CGFloat = 10
// 半径
let radius: CGFloat = 10
// 最大x值
let maxx = frame.maxX
// 最小x值
let minx = frame.minX
// 最大y值
let maxy = frame.maxY - bulge
// 最小y值
let miny = frame.minY
// 中间x值
let midx = frame.midX
let point1 = CGPoint(x: midx + bulge, y: maxy)
let point2 = CGPoint(x: midx, y: maxy + bulge)
let point3 = CGPoint(x: midx - bulge, y: maxy)
let path = UIBezierPath()
// 起始位置
path.move(to: point1)
path.addLine(to: point2)
path.addLine(to: point3)
path.addArc(withCenter: CGPoint(x: radius, y: maxy - radius), radius: radius, startAngle: CGFloat(Double.pi * 0.5), endAngle: CGFloat(Double.pi), clockwise: true)
path.addArc(withCenter: CGPoint(x: radius, y: radius), radius: radius, startAngle: CGFloat(Double.pi), endAngle: CGFloat(Double.pi * 1.5), clockwise: true)
path.addArc(withCenter: CGPoint(x: maxx - radius, y: radius), radius: radius, startAngle: CGFloat(Double.pi * 1.5), endAngle: CGFloat(Double.pi * 2), clockwise: true)
path.addArc(withCenter: CGPoint(x: maxx - radius, y: maxy - radius), radius: radius, startAngle: CGFloat(Double.pi * 2), endAngle: CGFloat(Double.pi * 0.5), clockwise: true)
let layer = CAShapeLayer()
layer.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
// 设置阴影
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 0)
layer.shadowOpacity = 5
layer.lineJoin = kCALineJoinMiter
layer.lineCap = kCALineCapSquare
layer.fillColor = UIColor.red.cgColor
layer.path = path.cgPath
return layer
}
最后添加到需要的view的layer里就可以了 注意这里一定要传bounds
self.layer.addSublayer(popLayer(with: bounds))
2.代码逻辑分析
红色的部分是原来view的大小 黄色部分是按图中数字的顺序画出来的 箭头2的位置是坐标系的原点 首先我们要确定三角尾巴的部分也就是5,6,7的坐标然后连起来也就是这段代码
let point1 = CGPoint(x: midx + bulge, y: maxy)
let point2 = CGPoint(x: midx, y: maxy + bulge)
let point3 = CGPoint(x: midx - bulge, y: maxy)
let path = UIBezierPath()
path.move(to: point1)
path.addLine(to: point2)
path.addLine(to: point3)
bulge是代表尾巴的长度所以我们在设置maxy的时候减去了bulge
// 最大y值
let maxy = frame.maxY - bulge
会得到这样的图像
然后我们要设置个带圆角的矩形也就是这段代码
path.addArc(withCenter: CGPoint(x: radius, y: maxy - radius), radius: radius, startAngle: CGFloat(Double.pi * 0.5), endAngle: CGFloat(Double.pi), clockwise: true)
path.addArc(withCenter: CGPoint(x: radius, y: radius), radius: radius, startAngle: CGFloat(Double.pi), endAngle: CGFloat(Double.pi * 1.5), clockwise: true)
path.addArc(withCenter: CGPoint(x: maxx - radius, y: radius), radius: radius, startAngle: CGFloat(Double.pi * 1.5), endAngle: CGFloat(Double.pi * 2), clockwise: true)
path.addArc(withCenter: CGPoint(x: maxx - radius, y: maxy - radius), radius: radius, startAngle: CGFloat(Double.pi * 2), endAngle: CGFloat(Double.pi * 0.5), clockwise: true)
addArc这个方法的
- 第一个参数是设置圆弧的中心点
- 第二个参数是设置圆弧的半径
- 第三个和第四个参数startAngle和endAngle是起始位置和结束位置
- 第五个参数true为顺时针false为逆时针
大家可能对startAngle和endAngle不太理解 看张图
如果我们想设置左上角为圆角的话 startAngle为π endAngle为1.5π
然后我们把四个圆角都设置好后会这样
我们把设置好的path传给CAShapeLayer就ok了
let layer = CAShapeLayer()
layer.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
// 设置阴影
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 0)
layer.shadowOpacity = 5
layer.lineJoin = kCALineJoinMiter
layer.lineCap = kCALineCapSquare
// 填充色
layer.fillColor = UIColor.yellow.cgColor
// 把设置好的path传递给layer
layer.path = path.cgPath
最后view的颜色设置为透明或者跟父视图一样的颜色就可以了
虽然drawrect也能画出来但是我听说drawrect挺耗资源的 我试了一下这个方法确实比drawrect性能上好那么一些 最后的最后祝大家5.1玩的开心 嘻嘻!