skip to Main Content

I have a view that needs to be displayed with a slanted corner on one side. I’ve already done it when the view has a background color like this:

enter image description here

But I also need it to be displayed with a clear background. After setting its background to clear and adding a border to it this is the output:

enter image description here

Here is the code for the custom view that I’m using to create the diagonal corner:

class PointedView: UIImageView {
    @IBInspectable var borderColor: UIColor = UIColor.clear {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }
    
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    
    @IBInspectable
    /// Percentage of the slant based on the width
    var slopeFactor: CGFloat = 15 {
        didSet {
            updatePath()
        }
    }
    
    private let shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = 0
        
        // with masks, the color of the shape layer doesn’t matter;
        // it only uses the alpha channel; the color of the view is
        // dictate by its background color
        shapeLayer.fillColor = UIColor.white.cgColor
        return shapeLayer
    }()
    
    override func layoutSubviews() {
        super.layoutSubviews()
        updatePath()
    }
    
    private func updatePath() {
        let path = UIBezierPath()
        
        // Start from x = 0 but the mid point of y of the view
        path.move(to: CGPoint(x: 0, y: bounds.midY*2))
        
        // Create the top slanting line
        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY))
        
        // Straight line from end of slant to the end of the view
        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        
        // Straight line to come down to the bottom, perpendicular to view
        path.addLine(to: CGPoint(x: bounds.maxX, y: ((bounds.maxY*3)/4) + 20))
        
        // Go back to the slant end position but from the bottom
        path.addLine(to: CGPoint(x: (bounds.maxX*3)/4, y: bounds.maxY))
        
        // Close path back to where you started
        path.close()
        
        shapeLayer.path = path.cgPath
        layer.mask = shapeLayer
    }
}

Is there any possible solution to this?

4

Answers


  1. Chosen as BEST ANSWER

    Managed to solve it by drawing another CAShapeLayer() following the same path as the original shape.

    let borderLayer = CAShapeLayer()
    borderLayer.path = path.cgPath
    borderLayer.lineWidth = 2
    borderLayer.strokeColor = borderColor.cgColor
    borderLayer.fillColor = UIColor.clear.cgColor
    borderLayer.frame = bounds
        
    layer.addSublayer(borderLayer)
    

    enter image description here


  2. if you are using StoryBoard with @IBInspectable you can try like thisenter image description here

    Login or Signup to reply.
  3. class PointedView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    func setup() {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = createBezierPath().cgPath
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.fillColor = UIColor.blue.cgColor
        shapeLayer.lineWidth = 1.0
        shapeLayer.position = CGPoint(x: 10, y: 10)
        self.layer.addSublayer(shapeLayer)
    }
    
    func createBezierPath() -> UIBezierPath {
        let path = UIBezierPath()
        
        // Start from x = 0 but the mid point of y of the view
        path.move(to: CGPoint(x: 0, y: bounds.midY*2))
        
        // Create the top slanting line
        path.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY))
        
        // Straight line from end of slant to the end of the view
        path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
        
        // Straight line to come down to the bottom, perpendicular to view
        path.addLine(to: CGPoint(x: bounds.maxX, y: ((bounds.maxY*3)/4) + 20))
        
        // Go back to the slant end position but from the bottom
        path.addLine(to: CGPoint(x: (bounds.maxX*3)/4, y: bounds.maxY))
        
        // Close path back to where you started
        path.close() // draws the final line to close the path
        return path
    }
    }
    
    Login or Signup to reply.
  4. Please use this method

    func roundCorners(corners: UIRectCorner = .allCorners, radius: CGFloat = 0.0, borderColor: UIColor = .clear, borderWidth: CGFloat = 0.0, clipToBonds: Bool = true) {
        clipsToBounds = clipToBonds
        layer.cornerRadius = radius
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor
        
        if corners.contains(.allCorners){
            layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
            return
        }
        
        var maskedCorners = CACornerMask()
        if corners.contains(.topLeft) { maskedCorners.insert(.layerMinXMinYCorner) }
        if corners.contains(.topRight) { maskedCorners.insert(.layerMaxXMinYCorner) }
        if corners.contains(.bottomLeft) { maskedCorners.insert(.layerMinXMaxYCorner) }
        if corners.contains(.bottomRight) { maskedCorners.insert(.layerMaxXMaxYCorner) }
        layer.maskedCorners = maskedCorners
    }
    

    and by using your UIVIEW

    View.roundCorners(corners: [.topLeft, .bottomLeft], radius: 20, borderColor: .clear, borderWidth: 0, clipToBonds: true)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search