ken
ken

Reputation: 668

Color of the triangle view drawn by UIBezierPath does not change

I would like to draw a triangle view and change the filled color programmatically.

Following is my code.

import UIKit

class ViewController: UIViewController {
    let triangleView = TriangleView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        triangleView.frame = CGRect(x: 0,
                                    y: 100,
                                    width: 50,
                                    height: 50)
        self.view.addSubview(triangleView)
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        triangleView.drawColor(color: .yellow)
    }
}


class TriangleView: UIView {
    let path = UIBezierPath()

    override func draw(_ rect: CGRect) {
        print("TriangleView draw")
        path.move(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: 0))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY))
        path.addLine(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.close()
        
        self.drawColor(color: .green)
        self.backgroundColor = .clear
    }
    
    func drawColor(color: UIColor) {
        print("TriangleView drawColor")

        color.setFill()
        path.lineWidth = 0
        path.fill()
        path.stroke()
    }
}

In this code, TriangleView draws a triangle filled with green color.

After that, ViewController changes filled color by yellow.

Following the result.

enter image description here

There are two problems.

  1. Background color is black though expectation is clear.

  2. Triangle color is not changed to yellow.

Could anyone give me advice ?

Upvotes: 0

Views: 40

Answers (1)

Raja Kishan
Raja Kishan

Reputation: 18974

Use UIGraphicsGetCurrentContext

class TriangleView: UIView {
    
    private var triangleColor: UIColor = .green {
        didSet {
            self.setNeedsDisplay()
        }
    }
    
    override func draw(_ rect: CGRect) {
        print("TriangleView draw")
        self.backgroundColor = .white // Set any background color
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        context.saveGState()
        defer { context.restoreGState() }
        
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: 0))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY))
        path.addLine(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.close()
        
        context.addPath(path.cgPath)
        context.setFillColor(triangleColor.cgColor)
        context.closePath()
        context.closePath()
        context.fillPath()
        context.restoreGState()
    }
    
    func drawColor(color: UIColor) {
        triangleColor = color
    }
}

Or you can use CAShapeLayer

class TriangleView: UIView {
    
    private let shapeLayer = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.initialConfig()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.initialConfig()
    }
    
    override func draw(_ rect: CGRect) {
        print("TriangleView draw")
        self.shapeLayer.frame = self.bounds
        drawShape()
    }
    
    private func initialConfig() {
        self.backgroundColor = .white
        self.shapeLayer.fillColor = UIColor.green.cgColor
        self.layer.addSublayer(shapeLayer)
    }
    
    private func drawShape() {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: 0))
        path.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY))
        path.addLine(to: CGPoint(x: 0, y: self.bounds.height / 2))
        path.close()
        
        shapeLayer.path = path.cgPath
    }
    
    func drawColor(color: UIColor) {
        self.shapeLayer.fillColor = color.cgColor
    }
}

Upvotes: 1

Related Questions