美文网首页iOS开发IOSiOS Developer
iOS不规则四边形视图

iOS不规则四边形视图

作者: is0bnd | 来源:发表于2016-10-24 15:19 被阅读847次

    最近项目中有需求绘制不规则的视图,完成后记录一下

    需求:视图的上下边倾斜,左右边竖直(如下图所示)
    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为视图的宽和高
    • 需要其他形状的重写绘制贝塞尔曲线的部分代码即可
    结语

    欢迎各位大神指出不足,如有更好的方法,也希望告知,谢谢!

    相关文章

      网友评论

        本文标题:iOS不规则四边形视图

        本文链接:https://www.haomeiwen.com/subject/zksluttx.html