горизонтальный градиент не работает с динамическим содержимым ширины - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь реализовать градиент для кнопки или вида в зависимости от требований.Но всякий раз, когда я пытаюсь сделать это для кнопки / вида, ширина которой является динамической (для горизонтального градиента), она загружается только наполовину.

func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.frame = self.bounds
    gradient.colors = colours.map { $0.cgColor }
    gradient.startPoint = orientation.startPoint
    gradient.endPoint = orientation.endPoint
    self.layer.insertSublayer(gradient, at: 0)
}

Градиентная ориентация получается с помощью следующего кода.

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.init(x: 0.0, y: 1.0), CGPoint.init(x: 1.0, y: 0.0))
    case .topLeftBottomRight:
        return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 1, y: 1))
    case .horizontal:
        return (CGPoint.init(x: 0.0, y: 0.5), CGPoint.init(x: 1.0, y: 0.5))
    case .vertical:
        return (CGPoint.init(x: 0.0, y: 0.0), CGPoint.init(x: 0.0, y: 1.0))
    }
}
}

Но если ширина равна 150, она отлично загружается для обоих видов / кнопок.Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Все подслои в UIView.layer не меняют свой размер автоматически при смене суперслоя.Переопределите метод UIView.layoutSubviews() и обновите границы CAGradientLayer из UIView.layer.

0 голосов
/ 30 мая 2018

Скорее всего, рамка вашей кнопки не такая, когда вы применяете градиент, как это будет позже.Вы можете попробовать распечатать границы в applyGradient для проверки.

Вы все равно должны добавить немного больше логики;так как это выглядит как подкласс представления, было бы здорово сохранить слой.В настоящее время, что вы ожидаете, если applyGradient вызывается дважды?Скорее всего, у вас будет 2 градиента.

Итак, вы бы добавили:

private var currentGradientLayer: CAGradientLayer?
func applyGradient(withColours colours: [UIColor], gradientOrientation orientation: GradientOrientation) {
    currentGradientLayer?.removeFromSuperlayer()
    currentGradientLayer = nil

    let gradient: CAGradientLayer = {
         let gradient: CAGradientLayer = CAGradientLayer()
         gradient.frame = self.bounds
         gradient.colors = colours.map { $0.cgColor }
         gradient.startPoint = orientation.startPoint
         gradient.endPoint = orientation.endPoint
    }()

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

Теперь, когда это сделано, вы должны попробовать переопределить еще 2 метода для исправления кадров:

override func layoutSubviews() {
    super.layoutSubviews()
    refreshGradientLayer()
}
override var frame: CGRect {
    didSet {
        refreshGradientLayer()
    }
}
private func refreshGradientLayer() {
    currentGradientLayer?.frame = bounds
}

Это должно обновить градиент в любом случае;layoutSubviews будет вызываться, когда ваше представление является макетом с ограничениями, и frame, когда это выполняется программно.

...