Как правильно генерировать случайный градиентный фон? - PullRequest
1 голос
/ 02 июля 2019

Я пытался создать функцию, которая генерирует случайный градиентный фон каждый раз, когда появляется новый контроллер представления, как показано с кодом, приведенным ниже, но я не могу заставить его работать должным образом. Проблема в том, что «случайные» цвета всегда одинаковы и генерируются в одном и том же порядке.

import Foundation

import UIKit

extension UIView {

    func setGradientBackground() {

        let redValue = CGFloat(drand48())
        let greenValue = CGFloat(drand48())
        let blueValue = CGFloat(drand48())

        let redValue2 = CGFloat(drand48())
        let greenValue2 = CGFloat(drand48())
        let blueValue2 = CGFloat(drand48())

        let random = UIColor(red: redValue, green: greenValue, blue: blueValue, alpha: 1).cgColor
        let random2 = UIColor(red: redValue2, green: greenValue2, blue: blueValue2, alpha: 1).cgColor

        let gradient = CAGradientLayer()
        gradient.frame = bounds
        gradient.colors = [random, random2]

        return layer.insertSublayer(gradient, at: 0)
    }
}

1 Ответ

1 голос
/ 02 июля 2019

Если вы используете drand48, вам нужно его заполнить (например, с помощью srand48).Быстрое и грязное решение состояло бы в том, чтобы посеять его с некоторым значением, полученным из времени из числа секунд, прошедших с некоторой контрольной даты или тому подобного.

Еще лучше, я бы предложил вместо этого использовать CGFloat.random(in: 0...1), чтоне требует какого-либо заполнения.

extension UIView {
    func addGradientBackground() {
        let random = UIColor.random().cgColor
        let random2 = UIColor.random().cgColor

        let gradient = CAGradientLayer()
        gradient.frame = bounds
        gradient.colors = [random, random2]

        layer.insertSublayer(gradient, at: 0)
    }
}

extension UIColor {
    static func random() -> UIColor {
        let red = CGFloat.random(in: 0...1)
        let green = CGFloat.random(in: 0...1)
        let blue = CGFloat.random(in: 0...1)
        return UIColor(red: red, green: green, blue: blue, alpha: 1)
    }
}

Для чего бы то ни было, мы должны оценить, что этот метод добавления подслоя проблематичен, если размер представления изменяется (например, вы поворачиваете устройство и т. д.)..).Вам придется вручную подключиться к viewDidLayoutSubviews или layoutSubviews и настроить этот градиентный слой frame.Вместо этого я мог бы предложить фактически иметь подкласс UIView, который делает этот градиентный слой.

@IBDesignable
class RandomGradientView: UIView {
    override static var layerClass: AnyClass { return CAGradientLayer.self }
    var gradientLayer: CAGradientLayer { return layer as! CAGradientLayer }

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

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

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        gradientLayer.colors = [UIColor.blue.cgColor, UIColor.red.cgColor]
    }
}

private extension RandomGradientView {
    func configure() {
        let random = UIColor.random().cgColor
        let random2 = UIColor.random().cgColor
        gradientLayer.colors = [random, random2]
    }
}

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

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

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