簡體   English   中英

CAGradientLayer 不顯示

[英]CAGradientLayer does not display

我已經查看了很多其他類似問題的答案,但似乎沒有一個答案能解決我的問題,所以尋求一點幫助。

我正在嘗試對 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)
  }
}

這就是我得到的:空按鈕

謝謝你的幫助!

對於已經花費數小時搜索的任何人(就像我一樣):

根據文檔,確保您的 colors 數組包含CGColor而不是UIColor

colors

定義每個漸變色標的顏色的 CGColorRef 對象數組。 動畫。

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

獎勵:如果您再次錯過它,這個小代碼片段將使應用程序崩潰(推薦使用#if DEBUG

extension CAGradientLayer {
    dynamic var colors: [Any]? {
        get { self.value(forKey: "colors") as? [Any] }
        set {
            if let newValue = newValue {
                for color in newValue {
                    if color is UIColor {
                        fatalError("CAGradientLayer.colors must contain only CGColor! UIColor was found")
                    }
                }
            }
            super.setValue(newValue, forKey: "colors")
        }
    }
}

自動布局不會影響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子類,並在按鈕框更新時更新漸變層frame。

參考

子層是從后到前的順序。 在索引0處插入圖層會將其放置在任何其他子圖層的后面。 我從未嘗試使用按鈕來做到這一點,但懷疑它至少有一個子圖層覆蓋了您要添加的漸變。

嘗試使用addSublayer()代替,它將把圖層放在sublayers數組的頂部。

編輯:

我構建了代碼的變體,當我將self.layer.insertSublayer(_:at:)更改為addSublayer() ,它可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM