CAGradientLayer не отображается - PullRequest
0 голосов
/ 20 ноября 2018

Я просмотрел кучу других ответов на подобные вопросы, но ни один из ответов, похоже, не решил мою проблему, поэтому ищу небольшую помощь.

Я пытаюсь применить вертикальный градиентна 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)
  }
}

Вот что я получаю: пустая кнопка

Спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Авторазметка не влияет на слои объектов 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)
}

enter image description here

Другой вариант - обновить свойство frame градиентного слоя в viewDidLayoutSubviews() или создать пользовательскийUIButton создает подкласс и обновляет кадр градиентного слоя всякий раз, когда обновляется кадр кнопки.

Ссылка

0 голосов
/ 20 ноября 2018

Подслои расположены в заднем порядке.Вставка слоя с индексом 0 поместит его позади любых других подслоев.Я никогда не пытался сделать это с помощью кнопки, но подозреваю, что у нее есть по крайней мере 1 подслой, покрывающий градиент, который вы пытаетесь добавить.

Попробуйте вместо этого использовать addSublayer(), который поместит слой наверхняя часть массива подслоев.

Редактировать:

Я создал вариант вашего кода, и когда я изменяю self.layer.insertSublayer(_:at:) на addSublayer(), он работает.

...