【问题标题】:CAGradientLayer does not displayCAGradientLayer 不显示
【发布时间】:2019-04-22 10:29:03
【问题描述】:

我查看了很多其他类似问题的答案,但似乎没有一个答案能解决我的问题,所以寻求一点帮助。

我正在尝试对 UIButton 应用垂直渐变,但渐变层并未显示在我的视图中。以下是相关代码:

let darkPurple = UIColor(displayP3Red: 61.0/255.0, green: 3.0/255.0, blue: 110.0/255.0, alpha: 1.0)
let lightPurple = UIColor(displayP3Red: 90.0/255.0, green: 32.0/255.0, blue: 130.0/255.0, alpha: 1.0)

let addButton = UIButton(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
addButton.title = "Start counting"
addButton.layer.cornerRadius = 30.0
addButton.layer.borderWidth = 1.0
addButton.layer.borderColor = darkPurple.cgColor
addButton.translatesAutoresizingMaskIntoConstraints = false
myView.addSubview(addButton)
addButton.applyGradient(with: [lightPurple, darkPurple], gradientOrientation: .vertical)

...以及应用渐变的代码:

typealias GradientPoints = (startPoint: CGPoint, endPoint: CGPoint)

enum GradientOrientation {
  case topRightBottomLeft
  case topLeftBottomRight
  case horizontal
  case vertical

  var startPoint: CGPoint {
    return points.startPoint
  }

  var endPoint: CGPoint {
    return points.endPoint
  }

  var points: GradientPoints {
    switch self {
    case .topRightBottomLeft:
      return (CGPoint(x: 0.0, y: 1.0), CGPoint(x: 1.0, y: 0.0))
    case .topLeftBottomRight:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1.0, y: 1.0))
    case .horizontal:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 1.0, y: 0.0))
    case .vertical:
      return (CGPoint(x: 0.0, y: 0.0), CGPoint(x: 0.0, y: 1.0))
    }
  }
}

extension UIView {
  func applyGradient(with colors: [UIColor], gradientOrientation orientation: GradientOrientation) {
    let gradient = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colors.map { $0.cgColor }
    gradient.startPoint = orientation.startPoint
    gradient.endPoint = orientation.endPoint
    gradient.borderColor = self.layer.borderColor
    gradient.borderWidth = self.layer.borderWidth
    gradient.cornerRadius = self.layer.cornerRadius
    gradient.masksToBounds = true
    gradient.isHidden = false

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

这是我得到的: empty button

感谢您的帮助!

【问题讨论】:

    标签: ios swift xcode uibutton cagradientlayer


    【解决方案1】:

    对于已经花费数小时搜索的人(就像我一样):

    根据文档,确保您的颜色数组包含 CGColor 而不是 UIColor

    颜色

    定义每个颜色的 CGColorRef 对象数组 梯度停止。动画。

    https://developer.apple.com/documentation/quartzcore/cagradientlayer/1462403-colors

    【讨论】:

    • 我怎么错过了!
    • @Prajwal 不是我们的错,colors 的类型为 [Any],责怪 Apple 开发人员)
    【解决方案2】:

    自动布局不会影响UIView 对象的图层,因此在计算UIButton 的帧之前太早应用了渐变图层。当渐变层的frame属性被赋值时,按钮的边界仍然等于CGRect.zero,并且渐变层框架以后永远不会更新。

    您会发现,如果您按钮框架计算完毕后添加渐变层,它会按预期工作。例如:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        let darkPurple = UIColor(displayP3Red: 61.0/255.0, green: 3.0/255.0, blue: 110.0/255.0, alpha: 1.0)
        let lightPurple = UIColor(displayP3Red: 90.0/255.0, green: 32.0/255.0, blue: 130.0/255.0, alpha: 1.0)
    
        addButton.applyGradient(with: [lightPurple, darkPurple], gradientOrientation: .vertical)
    }
    

    另一种选择是更新viewDidLayoutSubviews() 中渐变层的frame 属性或创建自定义UIButton 子类,并在按钮框架更新时更新渐变层框架。

    Reference

    【讨论】:

      【解决方案3】:

      子图层按从后到前的顺序排列。在索引 0 处插入图层会将其置于任何其他子图层之后。我从来没有尝试过使用按钮来做到这一点,但怀疑它至少有 1 个子层覆盖了您尝试添加的渐变。

      尝试改用addSublayer(),这会将图层放在子图层数组的顶部。

      编辑:

      我构建了您的代码的变体,当我将 self.layer.insertSublayer(_:at:) 更改为 addSublayer() 时,它可以工作。

      【讨论】:

      • 你是对的,当然。就我而言,我需要确保渐变显示在按钮标题后面,所以self.layer.insertSublayer(_:at:) 对我不起作用。然而,我确实有这个倒退,认为 0 将是顶部。谢谢指正!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-14
      相关资源
      最近更新 更多