【问题标题】:UIView with gradient not changing colors when button is tapped当点击按钮时,带有渐变的 UIView 不会改变颜色
【发布时间】:2020-09-10 00:48:07
【问题描述】:

当用户单击按钮时,它会随机化用于在大圆圈中创建渐变的颜色。在它下面是两个小圆圈,显示用于渐变的纯色。它们在开始时都正确显示(主圆圈是随机小圆圈颜色的渐变)但是当我点击按钮时,只有小圆圈改变颜色;大圆圈保持相同的渐变颜色。

扩展和视图控制器:

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) 以查看主 Circle 是否更改为 func newGradient()@objc func randomGradient(sender: UIButton) 中的这些颜色。它只会在func newGradient() 中更改我手动设置的内容,因此这意味着 VC 无法识别@objc func 中的主 Circle,但我不知道如何修复它...

感谢任何帮助!

单击“生成”按钮时的样子(大圆圈应显示为棕色和紫色)​​:

【问题讨论】:

  • 你到底想在这里实现什么?
  • 如果您可以共享完整代码或可以运行以重现问题的代码的最小版本,这将有助于提供具体的答案。

标签: ios swift cagradientlayer


【解决方案1】:

用这个更新你的功能,你必须删除旧层,然后插入新的子层。

解决方案 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 下。
  • yourView.layer.sublayers 这是包含所有子层的数组,目前您将gradientLayer 插入第 0 个位置...所以会有单个子层
【解决方案2】:

设置后更改渐变层颜色

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
        }
    }

}

【讨论】:

    【解决方案3】:

    渐变不会改变,因为您在现有渐变下方添加了新渐变

    extension UIView {
    
        func setupGradientBackground(colorOne: UIColor, colorTwo: UIColor) {
            let gradientLayer: CAGradientLayer = CAGradientLayer()
    
            ...
    
            // ⬇ There is a mistake. 
            self.layer.insertSublayer(gradientLayer, at: 0)
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 2015-02-10
      • 1970-01-01
      • 2020-07-29
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2012-04-16
      • 2020-11-21
      • 1970-01-01
      相关资源
      最近更新 更多