Фон диагонального градиента на UIView и повороте экрана

Я пытаюсь установить фон на моем UIView градиентом. В моем методе UIViewController's viewDidLoad есть следующее:

let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.blue70.cgColor, UIColor.blue60.cgColor, UIColor.blue70.cgColor]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1 )
gradientLayer.frame = self.view.bounds

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

Градиент отображается так, как ожидалось. Однако, когда я поворачиваю устройство, градиент не перерисовывается и больше не отображается должным образом. Вращение из портрета->пейзажа оставляет меня с пустой секцией справа или слева. Вращение из альбомной ориентации в портретную оставляет пустой раздел внизу. Я попытался переместить этот код в viewDidLayoutSubviews, но это не решило проблему. Любые рекомендации о том, как это сделать?

Ваша основная проблема заключается в том, что вы добавляете несколько слоев градиента внизу вашего представления, но будет виден только тот, который находится вверху. Что вам нужно, так это убедиться, что вы добавили только один градиентный слой и настроили его рамку в методе viewDidLayoutSubviews gradientLayer.frame = view.bounds

Leo Dabus 07.04.2019 03:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
1 479
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я бы порекомендовал добавить градиент в метод viewWillLayoutSubviews().

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    self.view.addGradiant()
}

Но теперь нам придется удалить старый слой при добавлении нового с новыми кадрами (на случай, если телефон вращается)

Затем мы можем сначала удалить слой и добавить новый, как в этом методе расширения.

extension UIView {

func addGradiant() {
    let GradientLayerName = "gradientLayer"

    if let oldlayer = self.layer.sublayers?.filter({$0.name == GradientLayerName}).first {
        oldlayer.removeFromSuperlayer()
    }

    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = [UIColor.blue.cgColor, UIColor.red.cgColor, UIColor.green.cgColor]
    gradientLayer.startPoint = CGPoint(x: 0, y: 0)
    gradientLayer.endPoint = CGPoint(x: 1, y: 1 )
    gradientLayer.frame = self.bounds
    gradientLayer.name = GradientLayerName

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

}

Сделайте градиентный слой свойством контроллера представления.

let gradientLayer = CAGradientLayer()

Добавьте градиентный слой в viewDidLoad так же, как и вы.

Установите фрейм в viewWillLayoutSubviews

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    gradientLayer.frame = self.view.bounds
}

Неа. Пробовал. Та же проблема с перерисовкой.

Shadowman 08.04.2019 16:55

Хотя вы можете сделать, как предлагают другие ответы, и обновить границы слоя градиента в viewDidLayoutSubviews, более многоразовый способ сделать что-то — создать подкласс градиентного представления, который layerClass является CAGradientLayer. У такого представления будет автоматически изменен размер слоя, чтобы соответствовать виду (поскольку слой градиента теперь является вспомогательным слоем для представления, а не каким-либо подслоем), и вы можете использовать это представление где угодно, просто изменив класс вашего представления в файле пера. или раскадровка:

class GradientView: UIView {
    var colors: [UIColor] = [.red, .white] {
        didSet {
            setup()
        }
    }
    var locations: [CGFloat] = [0,1] {
        didSet {
            setup()
        }
    }
    var startPoint: CGPoint = .zero  {
        didSet {
            setup()
        }
    }
    var endPoint: CGPoint = CGPoint(x: 1, y: 1) {
        didSet {
            setup()
        }
    }

    override class var layerClass : AnyClass { return CAGradientLayer.self }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        setup()
    }
    private func setup() {
        guard let layer = self.layer as? CAGradientLayer else {
            return
        }
        layer.colors = colors.map { $0.cgColor }
        layer.locations = locations.map { NSNumber(value: Double($0)) }
        layer.startPoint = startPoint
        layer.endPoint = endPoint
    }
}

Другие вопросы по теме