How to set gradient color to view in Dark mode ios?

心已入冬 提交于 2021-01-28 05:19:49

问题


I want to change the gradient color in dark mode. But it not changing. Gradient set once the view is setup. Color not changing while switching between light and dark mode.

 if let layer = layer as? CAGradientLayer {
        if let startGradientColor = startGradientColor, let endGradientColor = endGradientColor {
            layer.colors = [startGradientColor.cgColor, endGradientColor.cgColor]
        } else {
            layer.colors = gradientColors.map {$0.cgColor}
        }
        layer.startPoint = CGPoint(x: 0, y: 0)  // top
        layer.endPoint = CGPoint(x: 1, y: 1)    // bottom
    }

回答1:


You need to make your app react to changes to the trait collection, something like this:

extension YourViewController {
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)

        if #available(iOS 13.0, *) {
            guard traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) else {
                return
            }

            // redraw your layers here
        }
    }
}




回答2:


You can do this with "Dynamic Providers"

For example, in your custom gradient view class:

var startGradientColorDarkMode: UIColor = .white
var startGradientColorLightMode: UIColor = .black

lazy var myStartColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in
    if traitCollection.userInterfaceStyle == .dark {
        return self.startGradientColorDarkMode
    } else {
        return self.startGradientColorLightMode
    }
}

You can then use myStartColor.cgColor in your gradient colors array.

Here is a complete example:

class MyGradientView: UIView {

    // default Dark mode - white to orange
    var startGradientColorDarkMode: UIColor = .white
    {
        didSet {
            self.setNeedsLayout()
        }
    }
    var endGradientColorDarkMode: UIColor = .orange
    {
        didSet {
            self.setNeedsLayout()
        }
    }

    // default Light mode - black to blue
    var startGradientColorLightMode: UIColor = .black
    {
        didSet {
            self.setNeedsLayout()
        }
    }
    var endGradientColorLightMode: UIColor = .blue
    {
        didSet {
            self.setNeedsLayout()
        }
    }

    lazy var myStartColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in
        if traitCollection.userInterfaceStyle == .dark {
            return self.startGradientColorDarkMode
        } else {
            return self.startGradientColorLightMode
        }
    }

    lazy var myEndColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in
        if traitCollection.userInterfaceStyle == .dark {
            return self.endGradientColorDarkMode
        } else {
            return self.endGradientColorLightMode
        }
    }

    private var gradientLayer: CAGradientLayer!

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

    override func layoutSubviews() {
        self.gradientLayer = self.layer as? CAGradientLayer
        self.gradientLayer.colors = [myStartColor.cgColor, myEndColor.cgColor]

        self.gradientLayer.startPoint = CGPoint(x: 0, y: 0)  // top
        self.gradientLayer.endPoint = CGPoint(x: 1, y: 1)    // bottom
    }

}

class GradientTestViewController: UIViewController {

    let testView = MyGradientView(frame: CGRect(x: 40, y: 100, width: 240, height: 240))

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(testView)

        let tapGR = UITapGestureRecognizer(target: self, action: #selector(didTap))
        self.view.addGestureRecognizer(tapGR)

        // just for example
        // change colors from our defaults

        // change dark mode to red-to-yellow
        testView.startGradientColorDarkMode = .red
        testView.endGradientColorDarkMode = .yellow
        // change light mode to darkbown-to-lightBrown
        testView.startGradientColorLightMode = UIColor(red: 0.45, green: 0.3, blue: 0.25, alpha: 1.0)
        testView.endGradientColorLightMode = UIColor(red: 0.8, green: 0.65, blue: 0.3, alpha: 1.0)

    }

    @objc func didTap(tapGR: UITapGestureRecognizer) {
        // we can change the gradient colors on-the-fly
        if testView.startGradientColorDarkMode == UIColor.red {
            // change dark mode to blue-to-cyan
            testView.startGradientColorDarkMode = .blue
            testView.endGradientColorDarkMode = .cyan
            // change light mode to darkGreen-to-lightGreen
            testView.startGradientColorLightMode = UIColor(red: 0.0, green: 0.5, blue: 0.0, alpha: 1.0)
            testView.endGradientColorLightMode = .green
        } else {
            // change dark mode to red-to-yellow
            testView.startGradientColorDarkMode = .red
            testView.endGradientColorDarkMode = .yellow
            // change light mode to darkbown-to-lightBrown
            testView.startGradientColorLightMode = UIColor(red: 0.45, green: 0.3, blue: 0.25, alpha: 1.0)
            testView.endGradientColorLightMode = UIColor(red: 0.8, green: 0.65, blue: 0.3, alpha: 1.0)
        }
    }

}



回答3:


This is what I did, works great.

SomeGradientView.swift

class SomeGradientView: UIView {

    override open class var layerClass: AnyClass { return GradientLayer.self }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        if #available(iOS 13.0, *) {
            if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
                (layer as? GradientLayer)?.resetGradientColors()
                setNeedsDisplay()
            }
        }
    }
}

GradientLayer.swift

class GradientLayer: CAGradientLayer {

    // MARK: - Lifecycle
    override init() {
        super.init()
        setup()
    }

    override init(layer: Any) {
        super.init(layer: layer)
    }

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

    // MARK: - Private
    private func setup() {
        // gradient setup
        resetGradientColors()
        locations = ...
        opacity = 1
    }

    // MARK: - Internal
    /// Used for trait collection color appearance changes
    func resetGradientColors() {
        colors = [UIColor.systemRed, UIColor.systemBlue]
    }
}


来源:https://stackoverflow.com/questions/61077961/how-to-set-gradient-color-to-view-in-dark-mode-ios

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!