使用自动布局将渐变颜色应用于故事板视图

Applying gradient colour to storyboard view with auto layout

我在情节提要中添加了一个 UIView,并希望将其背景设置为渐变色。 这是我的代码

extension UIView {
    func setGradientBackground(colors: [CGColor]) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = colors
        gradientLayer.locations = [0.0, 1.0]
        gradientLayer.frame = self.bounds
        self.layer.insertSublayer(gradientLayer, at:0)
    }
}

并在 viewcontroller、

viewSocial.setGradientBackground(colors: [UIColor.gradientBottomColor.cgColor, UIColor.gradientTopColor.cgColor])

但这会创建双渐变图层。 see the image

我已经尝试为 GradientLayer 添加 class,如前所述 。但这不允许设置故事板的视图。给出弱变量的警告。

这是制作 @IBDesignable 渐变视图的一种方法。它使用默认的从上到下的渐变方向:

@IBDesignable
class MyGradientView: UIView {
    
    @IBInspectable var color1: UIColor = .red {
        didSet { setNeedsDisplay() }
    }
    @IBInspectable var color2: UIColor = .yellow {
        didSet { setNeedsDisplay() }
    }

    private var gradientLayer: CAGradientLayer!
    
    override class var layerClass: AnyClass {
        return CAGradientLayer.self
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        // use self.layer as the gradient layer
        gradientLayer = self.layer as? CAGradientLayer
        gradientLayer.colors = [color1.cgColor, color2.cgColor]
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        gradientLayer.colors = [color1.cgColor, color2.cgColor]
    }
    
}

“color1”和“color2”有 @IBInspectable 变量...在 Attributes Inspector 中更改它们将反映在 Storyboard 中。

不需要任何额外的代码,例如您当前使用 setGradientBackground()

的方法

这里是@IBDesignable渐变视图的代码。您可以从 Storyboard.

使用从上到下和从左到右
private var startGradientColorAssociatedKey : UIColor = .black
private var endGradientColorAssociatedKey : UIColor = .black
private var observationGradientView: NSKeyValueObservation?

extension UIView {


@IBInspectable var startGradientColor: UIColor {
    get {
        if let color = objc_getAssociatedObject(self, &startGradientColorAssociatedKey) as? UIColor {
            return color
        } else {
            return .black
        }
    } set {
        objc_setAssociatedObject(self, &startGradientColorAssociatedKey, newValue, .OBJC_ASSOCIATION_RETAIN)
    }
}

@IBInspectable var endGradientColor: UIColor {
    get {
        if let color = objc_getAssociatedObject(self, &endGradientColorAssociatedKey) as? UIColor {
            return color
        } else {
            return .black
        }
    } set {
        objc_setAssociatedObject(self, &endGradientColorAssociatedKey, newValue, .OBJC_ASSOCIATION_RETAIN)
    }
}


@IBInspectable
var isTopToBottomGradient: Bool {
    get {
        return self.isTopToBottomGradient
    }
    set {
        DispatchQueue.main.async {
            if newValue {
                self.setGradientBackground(colorTop: self.startGradientColor, colorBottom: self.endGradientColor)
            } else {
                self.setGradientBackground(colorLeft: self.startGradientColor, colorRight: self.endGradientColor)
            }
        }
    }
}


func setGradientBackground(colorLeft: UIColor, colorRight: UIColor) {
    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = [colorLeft.cgColor, colorRight.cgColor]
    gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
    gradientLayer.locations = [0, 1]
    gradientLayer.frame = bounds
    observationGradientView = self.observe(\.bounds, options: .new) { [weak gradientLayer] view, change in
        if let value =  change.newValue {
            gradientLayer?.frame = value
        }
    }
    
    layer.insertSublayer(gradientLayer, at: 0)
}
}

Use from Storyboard : 如果你想设置从上到下的渐变那么设置ON isTopToBottomGradient键。默认值为 OFF