Search code examples
iosswiftborder

Bottom Right Corner Curve Incorrect Position (Swift)


The curve I created isn't what I intended:

  • this is what I'm aiming for

    (Desired Curve: image of the desired curve.

  • this is what I have achieved so far:

    This is what i have done.

class ConerViewBootomRight: UIView {
    
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()
    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
        
    }
    //This method does the necessary UI adjustments
    func setup()
    {
        if #available(iOS 13.0, *) {
            
            let cornerRadius: CGFloat = 80.0 // Set the corner radius
            let path = UIBezierPath()
            path.move(to: CGPoint(x: 0, y: 0))
            path.addLine(to: CGPoint(x: self.bounds.width, y: 0))
            path.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height - cornerRadius))
            path.addQuadCurve(to: CGPoint(x: self.bounds.width - cornerRadius, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width, y: self.bounds.height))
            path.addLine(to: CGPoint(x: 0, y: self.bounds.height))
            path.close()

            let maskLayer = CAShapeLayer()
            maskLayer.path = path.cgPath
            self.layer.mask = maskLayer

         }
    }
}

Please help me I'm beginner in swift.


Solution

  • You are calling setup in the initialisers. This means that all the accesses to self.bounds.width and self.bounds.height will evaluate to whatever dimensions the bounds of the view initially has. If the bounds of the view changes later down the line (e.g. being laid out by AutoLayout constraints), the path you created will still use the old width and height.

    You should create the path in layoutSubviews, so that a new path is created each time the view is laid out (which would potentially give it a different bounds).

    class ConerViewBootomRight: UIView {
        
        var maskLayer: CAShapeLayer!
        
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)!
            setup()
        }
        
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            setup()
            
        }
        
        func setup()
        {
            maskLayer = CAShapeLayer()
            self.layer.mask = maskLayer
        }
        
        override func layoutSubviews() {
            super.layoutSubviews()
            let cornerRadius: CGFloat = 80.0
            let path = UIBezierPath()
            path.move(to: CGPoint(x: 0, y: 0))
            path.addLine(to: CGPoint(x: self.bounds.width, y: 0))
            path.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height - cornerRadius))
            path.addQuadCurve(to: CGPoint(x: self.bounds.width - cornerRadius, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width, y: self.bounds.height))
            path.addLine(to: CGPoint(x: 0, y: self.bounds.height))
            path.close()
            maskLayer.path = path.cgPath
        }
    }