最近项目中有需求绘制不规则的视图,完成后记录一下
需求:视图的上下边倾斜,左右边竖直(如下图所示)
xiaoguo.png解决步骤:
1.让它看起来不规则(视图处理): 使用了view.layer.mask约束视图边界
2.让它用起来不规则(事件处理): 重写 func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool
自定义视图类代码
/// 自定义结构体, 表示各个方向沿竖直方向向内收缩的距离(大于等于零)
struct PathOffSet {
var leftTop: CGFloat
var leftBottom: CGFloat
var rightTop: CGFloat
var rightBottom: CGFloat
init(leftTop: CGFloat, leftBottom: CGFloat, rightTop: CGFloat, rightBottom: CGFloat) {
self.leftTop = leftTop
self.leftBottom = leftBottom
self.rightTop = rightTop
self.rightBottom = rightBottom
}
func isEmpty() -> Bool {
return (leftBottom == 0 && leftTop == 0 && rightTop == 0 && rightBottom == 0)
}
}
// 不规则四边形的视图, 其中两条竖边平行
// 兼容xib和Storyboard
// 创建完成之后只需要设置offSet即可
// 只在对应不规则四边形内响应事件
class PathView: UIView {
var offSet = PathOffSet(leftTop: 0, leftBottom: 0, rightTop: 0, rightBottom: 0) {
didSet {
self.setNeedsLayout()
}
}
private var maskLayer = CAShapeLayer()
private var path: UIBezierPath?
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
setPath(offSet)
}
// 设置边界约束
func setPath(offSet: PathOffSet) {
if offSet.isEmpty() {
return
}
let path = UIBezierPath()
path.moveToPoint(CGPointMake(0, 5 + offSet.leftTop))
path.addQuadCurveToPoint(CGPointMake(5, offSet.leftTop), controlPoint: CGPointMake(0, offSet.leftTop))
path.addLineToPoint(CGPointMake(w - 5, offSet.rightTop))
path.addQuadCurveToPoint(CGPointMake(w, 5 + offSet.rightTop), controlPoint: CGPointMake(w, offSet.rightTop))
path.addLineToPoint(CGPointMake(w, h - 5 - offSet.rightBottom))
path.addQuadCurveToPoint(CGPointMake(w - 5, h - offSet.rightBottom), controlPoint: CGPointMake(w, h - offSet.rightBottom))
path.addLineToPoint(CGPointMake(5, h - offSet.leftBottom))
path.addQuadCurveToPoint(CGPointMake(0, h - 5 - offSet.leftBottom), controlPoint: CGPointMake(0, h - offSet.leftBottom))
path.addLineToPoint(CGPointMake(0, 5 + offSet.leftTop))
path.closePath()
self.path = path
maskLayer.path = path.CGPath
maskLayer.fillColor = UIColor.blackColor().CGColor
maskLayer.strokeColor = UIColor.redColor().CGColor
maskLayer.frame = bounds
maskLayer.contentsCenter = CGRectMake(0.5, 0.5, 0.1, 0.1)
maskLayer.contentsScale = UIScreen.mainScreen().scale
layer.mask = maskLayer
}
// 重写点击判定方法
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
if path != nil {
return path!.containsPoint(point)
}else {
return super.pointInside(point, withEvent: event)
}
}
}
使用方法
使用代码/xib/storyboard创建自定义类或其子类的视图, 设置offset属性即可
注意事项
- PathOffSet的所有属性的值都应该大于等于零, 或者自行修改进行限制, 小于零时直接设置为零或者抛出异常
- setPath函数中的w,h为视图的宽和高
- 需要其他形状的重写绘制贝塞尔曲线的部分代码即可
结语
欢迎各位大神指出不足,如有更好的方法,也希望告知,谢谢!
网友评论