最近項目中有需求繪制不規則的視圖,完成后記錄一下
需求:視圖的上下邊傾斜,左右邊豎直(如下圖所示)
xiaoguo.png
解決步驟:
1.讓它看起來不規則(視圖處理): 使用了 view.layer.mask 約束視圖邊界
2.讓它用起來不規則(事件處理): 重寫 func pointInside(point: CGPoint, withEvent event: UIEvent?) -gt; 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() -gt; Bool { return (leftBottom == 0 amp;amp; leftTop == 0 amp;amp; rightTop == 0 amp;amp; 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?) -gt; Bool { if path != nil { return path!.containsPoint(point) }else { return super.pointInside(point, withEvent: event) } } }
使用方法
使用 代碼/xib/storyboard 創建自定義類或其子類的視圖, 設置 offset 屬性即可
注意事項
- PathOffSet的所有屬性的值都應該大于等于零, 或者自行修改進行限制, 小于零時直接設置為零或者拋出異常
- setPath函數中的w,h為視圖的寬和高
- 需要其他形狀的重寫繪制貝塞爾曲線的部分代碼即可
結語
歡迎各位大神指出不足,如有更好的方法,也希望告知,謝謝!
Tags: iOS開發
文章來源:http://www.jianshu.com/p/7d7e63b7fe9c