0

I am trying to make a UIView with pointed edges like this. Did some searching around and found some questions with slanting just one edge like this one but can't find an answer with intersecting (points) edges like the one in the picture that dynamically sizes based on the UIView height.

Tyler Rutt
  • 49
  • 4

1 Answers1

2

I used Rob's answer to create something like this:

@IBDesignable
class PointedView: UIView
{
    @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))
        
        // Calculate the slant based on the slopeFactor
        let slantEndX = bounds.maxX * (slopeFactor / 100)
        
        // Create the top slanting line
        path.addLine(to: CGPoint(x: slantEndX, 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))
        
        // Go back to the slant end position but from the bottom
        path.addLine(to: CGPoint(x: slantEndX, y: bounds.maxY))
        
        // Close path back to where you started
        path.close()
        
        shapeLayer.path = path.cgPath
        layer.mask = shapeLayer
    }
}

The end result should give you a view close to what you which can be modified on the storyboard

Custom UIView with pointed edge tag view iOS swift

And can also be created using code, here is a frame example since the storyboard showed its compatibility with autolayout

private func createPointedView()
{
    let pointedView = PointedView(frame: CGRect(x: 0,
                                                y: 0,
                                                width: 200,
                                                height: 60))
    
    pointedView.backgroundColor = .red
    pointedView.slopeFactor = 50
    pointedView.center = view.center
    
    view.addSubview(pointedView)
}
Shawn Frank
  • 4,381
  • 2
  • 19
  • 29