Unable to Apply Colors to CAGradientLayer in Swift

37 Views Asked by At
class ViewController: UIViewController {

    let label = UILabel()
    private var rightGradient: CAGradientLayer!
    let view2 = UIView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label.text = """
        (A) It happened in the middle of a night when I was eight years old. I was sleeping in my bed. But when I shifted onto my right side to check the time on my clock, I saw (a) a man crouching next to my bed. He had dark blue skin, and his blue eyes seemed to be reflecting a lot of light as if the moon had been shining on him. And his hair was the darkest shade of black I've ever seen.

        (B) The next morning, I asked my dad if he remembered me calling him the night before, but he said no. I told him about what had happened, but he thought it had been just a silly dream. But it couldn't have been a dream because (b) he was wearing the same pajamas he had worn that night when he came to turn on the lights in my room.

        (C) I didn't know what to think and what to do. He didn't move, nor did he blink. (c) He just stared at me, so all I could do to escape his penetrating eyes was close my eyes, call out to my dad, and cover my face with my blanket. I dared not turn to the other side of the bed in fear that (d) he'd be there, too.
        (D) After a while, my dad came into my room and asked me what was wrong. When I opened my eyes to answer, however, I couldn't find (e) the man. My dad checked if there was anything strange, but everything in my room was exactly how it was. He returned to his room assuring me that there was nothing strange in my room.
        """
        
        view.addSubview(view2)
        view2.backgroundColor = .green
        view2.snp.makeConstraints {
            $0.leading.bottom.trailing.equalToSuperview()
            $0.height.equalTo(100)
        }

        view.addSubview(label)
        label.numberOfLines = 0
        label.snp.makeConstraints {
            $0.top.leading.trailing.equalToSuperview()
            $0.bottom.equalTo(view2.snp.top)
        }
        
        setupGradients()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        rightGradient.frame = label.bounds
    }
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        updateGradientColors()
    }
    
    private func setupGradients() {
        rightGradient = CAGradientLayer()
        rightGradient.frame = label.bounds
        rightGradient.startPoint = CGPoint(x: 0.5, y: 0.5)
        rightGradient.endPoint = CGPoint(x: 1, y: 0.5)
        label.layer.mask = rightGradient
        
        updateGradientColors()
    }
    
    private func updateGradientColors() {
        if self.traitCollection.userInterfaceStyle == .dark {
            print("dark")
            rightGradient.colors = [UIColor.brown.cgColor, UIColor.clear.cgColor]
        } else {
            print("light")
            rightGradient.colors = [UIColor.green.cgColor, UIColor.clear.cgColor]
        }
    }
}


Screenshot attached here-

enter image description here

Despite trying to set the gradient colors to green and black, I'm not seeing any color change on the label. The gradient itself seems to be working, as it affects the transparency, but the actual colors are not being applied as I expected. Am I missing something in my code or overlooking a key step in setting up the gradient colors based on the user interface style? Any guidance on how to achieve the desired color change based on the interface style would be greatly appreciated. Thank you!

I have done a lot of research and refined my code to reach this point.

1

There are 1 best solutions below

0
jrturton On

Kurt Revis' comment about using the gradient as a mask is correct, this will only use the transparency of the gradient and not the colour components. However, if you fix that, you will hit another problem.

UIColor.clear and UIColor.green (or .brown, or whatever) are not in the same colour space, so gradient layers can't calculate the transition for you. If you want a gradient to move from colour A to clear, then set it up like this:

let base = UIColor.green
rightGradient.colors = [base.cgColor, base.withAlphaComponent(0).cgColor]