UIView添加渐变颜色,但按钮被点击后颜色不会改变

3
当用户点击按钮时,它会随机使用颜色来创建大圆中的渐变效果。在大圆下方有两个小圆显示用于渐变的实色。一开始它们都正确地显示(主圆是随机小圆颜色的渐变),但当我点击按钮时,只有小圆改变颜色,大圆保持相同的渐变颜色。
扩展和视图控制器:
extension UIView {
func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {
        let gradientLayer: CAGradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
        gradientLayer.frame = self.bounds

        self.layer.insertSublayer(gradientLayer, at: 0)
    }
}

extension UIColor {
     static var random: UIColor {
        return UIColor(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1), alpha: 1.0)
    }
}

class GradientController: UIViewController {
    let gradientView = GradientView()
    let leftGradientColor: UIColor = .random
    let rightGradientColor: UIColor = .random
}

    override func viewDidLoad() {
        super.viewDidLoad()
        view = gradientView
        newGradient()
    }

    func newGradient() {
        gradientView.mainCircleView.setupGradientBackground(colorOne: leftGradientColor, colorTwo: rightGradientColor)
        gradientView.colorCircleLeftView.backgroundColor = leftGradientColor
        gradientView.colorCircleRightView.backgroundColor = rightGradientColor
        gradientView.gradientGenerateButton.addTarget(self, action: #selector(randomGradient(sender:)), for: .touchUpInside)
    }

    @objc func randomGradient(sender: UIButton)
    {
        let leftGradient = UIColor.random
        let rightGradient = UIColor.random

        gradientView.colorCircleLeftView.backgroundColor = leftGradient
        gradientView.colorCircleRightView.backgroundColor = rightGradient

        //Here is where it's not changing colors. Doesn't seem like the VC recognizes it in this function
        gradientView.mainCircleView.setupGradientBackground(colorOne: leftGradient, colorTwo: rightGradient)
    }

查看:

class GradientView: UIView {
//circle's UIView code in Extensions
    let mainCircleView = UIView().circleView(width: 380, height: 380)
    let colorCircleLeftView = UIView().circleView(width: 40, height: 40)
    let colorCircleRightView = UIView().circleView(width: 40, height: 40)

...

    func setupLayout() {
    ...
    }
}

我尝试的是将mainCircleView的颜色更改为纯UIColors,例如gradientView.mainCircleView.setupGradientBackground(colorOne: .red, colorTwo: .orange),以查看主圆在func newGradient()@objc func randomGradient(sender: UIButton)中是否都会更改为这些颜色。只有在我手动设置的func newGradient()中才会更改,这意味着VC在@objc func中无法识别主圆,但我不知道如何解决它...

感谢您的任何帮助!

当我点击“生成”按钮时它的样子(大圆应该显示为棕色和紫色):enter image description here


你在这里究竟想要实现什么? - Frankenstein
1
如果您能分享完整的代码或最小化的可运行代码以重现问题,那么这将有助于提供具体的答案。 - Felix Marianayagam
3个回答

2

请使用以下代码更新您的函数,您需要删除旧的图层并插入新的子图层。

解决方案1:

   func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {

        if let gradientLayer = (self.layer.sublayers?.compactMap { $0 as? CAGradientLayer })?.first {
               gradientLayer.removeFromSuperlayer()
        }

        let gradientLayer: CAGradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
        gradientLayer.frame = self.bounds
        self.layer.insertSublayer(gradientLayer, at: 0)
    }

解决方案2:

func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {

    let gradientLayer = layer.sublayers?.first as? CAGradientLayer ?? CAGradientLayer()

    gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
    gradientLayer.locations = [0.0, 1.0]
    gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
    gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
    gradientLayer.frame = self.bounds

    guard gradientLayer.superlayer != self else {
      return
    }
    layer.insertSublayer(gradientLayer, at: 0)
}

解决方案3:你可以给你的CAGradientLayer设置名称,这将有助于你删除特定的层。

   func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {
        for layer in layer.sublayers ?? [] {
            if layer.name == "GradientLayer" {
                layer.removeFromSuperlayer()
            }
        }

        let gradientLayer: CAGradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorOne.cgColor, colorTwo.cgColor]
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0)
        gradientLayer.name = "GradientLayer"
        gradientLayer.frame = self.bounds

        self.layer.insertSublayer(gradientLayer, at: 0)
    }

谢谢您的建议!它们三个都有效。作为后续问题,我如何知道一个视图是否有多个层?我对Swift还比较新,没有意识到主圆中的颜色在Superlayer下发生了变化。 - Stephanie Chiu
yourView.layer.sublayers 这是一个数组,包含了所有的子层,目前您正在将 gradientLayer 插入到第0个位置...因此只会有一个子层。 - Saifan Nadaf

0

因为在现有梯度下面添加新的梯度不会改变梯度。

extension UIView {

    func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {
        let gradientLayer: CAGradientLayer = CAGradientLayer()

        ...

        // ⬇ There is a mistake. 
        self.layer.insertSublayer(gradientLayer, at: 0)
    }
}

你应该用这个新的渐变替换当前的渐变。或者在旧的渐变上方插入一个新的。


0
更改设置后的渐变图层颜色
extension CALayer {   

    func updateGradientColors(_ colors:CGColor...) {
        if let layer = sublayers?.first as? CAGradientLayer {
            let frame = CGRect(origin: self.bounds.origin, size: CGSize(width: self.bounds.size.width, height: self.bounds.size.height))
            layer.frame = frame
            layer.colors = colors
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接