Search code examples
swiftuiviewcalayer

UIView border with partial border


I have UIView which I need to draw a border only partial part view, how do I do in using UIBezierPathenter image description here


Solution

  • If you want to use UIBezierPath, you could choose the "silly" way:

    • stroke the full border of your view
    • "cover up" the part where you don't want the border to exist with the view's background color, by drawing a rectangle on top of the border.
    class MyView: UIView {
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        
        private func commonInit() {
            layer.cornerRadius = 3
            backgroundColor = .white
            layer.masksToBounds = true
        }
        
        override func draw(_ rect: CGRect) {
            let borderPath = UIBezierPath(roundedRect: bounds, cornerRadius: 3)
            borderPath.lineWidth = 7
            UIColor.gray.setStroke()
            borderPath.stroke()
            let covering = UIBezierPath(rect: CGRect(x: 20, y: -10, width: self.bounds.width - 40, height: 20))
            backgroundColor?.setFill()
            covering.fill()
        }
    }
    

    Output:

    enter image description here

    Other than that, I can't think of an easy way to do this.

    However, if you can use CAShapeLayer...

    You should set the strokeEnd and strokeStart properties of a CAShapeLayer added as a sublayer of your view's layer.

    Example:

    class MyView: UIView {
        override init(frame: CGRect) {
            super.init(frame: frame)
            commonInit()
        }
        
        required init?(coder: NSCoder) {
            super.init(coder: coder)
            commonInit()
        }
        
        private func commonInit() {
            layer.cornerRadius = 3
            let border = CAShapeLayer()
            // make sure this path coincides with the border of the view
            border.path = UIBezierPath(roundedRect: bounds, cornerRadius: 3).cgPath
    
            // you should tweak these numbers
            border.strokeStart = 0.3
            border.strokeEnd = 0.7
    
            border.strokeColor = UIColor.gray.cgColor
            border.lineWidth = 3
            border.fillColor = nil
            layer.addSublayer(border)
            backgroundColor = .white
        }
    }
    

    Output:

    enter image description here