Градиент из UIView после ориентационного перехода - PullRequest
1 голос
/ 09 марта 2020

У меня есть расширение для UIView для применения градиента:

    extension UIView {

    func applyGradient(colors: [CGColor]) {

        self.backgroundColor = nil
        let gradientLayer = CAGradientLayer()
        gradientLayer.frame = self.bounds // Here new gradientLayer should get actual UIView bounds
        gradientLayer.cornerRadius = self.layer.cornerRadius
        gradientLayer.colors = colors
        gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
        gradientLayer.masksToBounds = true

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

В моем подклассе UIView я создаю все мои представления и устанавливаю ограничения:

private let btnSignIn: UIButton = {
    let btnSignIn = UIButton()

    btnSignIn.setTitle("Sing In", for: .normal)
    btnSignIn.titleLabel?.font = UIFont(name: "Avenir Medium", size: 35)

    btnSignIn.layer.cornerRadius = 30
    btnSignIn.clipsToBounds = true
    btnSignIn.translatesAutoresizingMaskIntoConstraints = false

    return btnSignIn
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    addSubViews()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    addSubViews()
}

func addSubViews() {
    self.addSubview(imageView)
    self.addSubview(btnSignIn)
    self.addSubview(signUpstackView)
    self.addSubview(textFieldsStackView)
    setConstraints()
}

У меня есть переопределенная функция layoutSubviews, которая вызывается каждый раз, когда изменяются границы вида (включая переход ориентации), где я вызываю applyGradient.

override func layoutSubviews() {
    super.layoutSubviews()
    btnSignIn.applyGradient(colors: [Colors.ViewTopGradient, Colors.ViewBottomGradient])
}

Проблема заключается в том, что после ориентационного перехода градиент применяется по какой-то причине неправильно. .

Смотрите скриншот, пожалуйста enter image description here

Что мне здесь не хватает?

1 Ответ

1 голос
/ 09 марта 2020

Если вы посмотрите на свою кнопку, вы увидите два градиента. Это потому, что layoutSubviews вызывается как минимум дважды: сначала, когда представление было впервые представлено, и снова после изменения ориентации. Итак, вы добавили как минимум два градиентных слоя.

Вы хотите изменить это так, чтобы вы только insertSublayer один раз (например, во время создания экземпляра представления), и поскольку layoutSubviews можно вызывать несколько раз, он должен ограничиваться только настройкой существующих слоев, а не добавление любого.

Вы также можете просто использовать свойство класса layerClass, чтобы сделать основной слой кнопки градиентом, и тогда вам вообще не придется настраивать рамки слоя:

@IBDesignable
public class RoundedGradientButton: UIButton {

    static public override var layerClass: AnyClass { CAGradientLayer.self }
    private var gradientLayer: CAGradientLayer      { layer as! CAGradientLayer }

    @IBInspectable var startColor: UIColor = .blue  { didSet { updateColors() } }
    @IBInspectable var endColor: UIColor = .red     { didSet { updateColors() } }

    override public init(frame: CGRect = .zero) {
        super.init(frame: frame)
        configure()
    }

    required public init?(coder: NSCoder) {
        super.init(coder: coder)
        configure()
    }

    override public func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = min(bounds.height, bounds.width) / 2
    }
}

private extension RoundedGradientButton {
    func configure() {
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        updateColors()

        titleLabel?.font = UIFont(name: "Avenir Medium", size: 35)
    }

    func updateColors() {
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
    }
}

Этот метод избавляет от необходимости настраивать frame слоя вручную и также приводит к лучшему воспроизведению в середине анимации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...