iOS不規則四邊形視圖

分類:技術 時間:2016-10-24

最近項目中有需求繪制不規則的視圖,完成后記錄一下

需求:視圖的上下邊傾斜,左右邊豎直(如下圖所示)

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


ads
ads

相關文章
ads

相關文章

ad