简体   繁体   English

Swift:UIView 的背景渐变

[英]Swift: Background gradient for UIView

I'm having trouble trying to add a gradient background to UIView .我在尝试向UIView添加渐变背景时遇到问题。 I made an extension of UIView and added the following method:我做了一个UIViewextension并添加了以下方法:

func setGradientBackground(colorTop: UIColor, colorBottom: UIColor) {
    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = [colorTop, colorBottom]
    gradientLayer.frame = bounds

    layer.insertSublayer(gradientLayer, at: 0)
}

Then I call:然后我打电话:

separatorView.setGradientBackground(colorTop: .clear, colorBottom: .red)

But it doesn't work.但它不起作用。 The view is presented but its background is entirely clear.该视图已呈现,但其背景完全清楚。 I tried as well with CGColor我也尝试过CGColor

There were 2 problems:有2个问题:

  • I needed to set the start and end points to provide a gradient direction:我需要设置起点和终点以提供渐变方向:

     func setGradientBackground(colorTop: UIColor, colorBottom: UIColor) { let gradientLayer = CAGradientLayer() gradientLayer.colors = [colorBottom.cgColor, colorTop.cgColor] gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0) gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0) gradientLayer.locations = [0, 1] gradientLayer.frame = bounds layer.insertSublayer(gradientLayer, at: 0) }
  • And the second issue was that CAGradientLayer takes effect after the view is layed out.第二个问题是CAGradientLayer在view CAGradientLayer后生效。 I solved that calling setGradientBackground() on viewDidAppear :我解决了在viewDidAppear上调用setGradientBackground()问题:

     override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) separatorView.setGradientBackground(colorTop: .clear, colorBottom: Colors.darkGrey) }

Update your method to the code blow:将您的方法更新为代码打击:

func setGradientBackground(colorTop: UIColor, colorBottom: UIColor){
    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = [colorTop.cgColor, colorBottom.cgColor]
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
    gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
    gradientLayer.locations = [NSNumber(floatLiteral: 0.0), NSNumber(floatLiteral: 1.0)]
    gradientLayer.frame = self.bounds

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

Moayad's answer worked best for me but it was backwards with top color as bottom so i reversed the function he posted. Moayad 的答案对我来说效果最好,但它以顶部颜色为底部向后,所以我反转了他发布的功能。

Swift 4斯威夫特 4

    func setGradientBackground(colorTop: UIColor, colorBottom: UIColor){
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [colorBottom.cgColor, colorTop.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
        gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
        gradientLayer.locations = [0, 1]
        gradientLayer.frame = bounds

        layer.insertSublayer(gradientLayer, at: 0)
}

For @IBDesignable: You can custom your UI on storyboard.对于@IBDesignable:您可以在情节提要上自定义您的 UI。 It is easier to use.它更容易使用。

@IBDesignable class GradientView: UIView {

    @IBInspectable var startColor: UIColor = .blue {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var endColor: UIColor = .green {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var shadowColor: UIColor = .yellow {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var shadowX: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var shadowY: CGFloat = -3 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var shadowBlur: CGFloat = 3 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var startPointX: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var startPointY: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var endPointX: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var endPointY: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            setNeedsLayout()
        }
    }

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

    override func layoutSubviews() {
        let gradientLayer = layer as! CAGradientLayer
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
        gradientLayer.startPoint = CGPoint(x: startPointX, y: startPointY)
        gradientLayer.endPoint = CGPoint(x: endPointX, y: endPointY)
        layer.cornerRadius = cornerRadius
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOffset = CGSize(width: shadowX, height: shadowY)
        layer.shadowRadius = shadowBlur
        layer.shadowOpacity = 1
    }
}

This does work for my project这对我的项目有效

/**
 set a gradient to a view
 gradientColors must be cgColors
 gradientColors and locations must have the same array size
 example:
 let gradientColors = [UIColor.red.cgColor,UIColor.blue.cgColor,UIColor.yellow.cgColor]
 let locations:[NSNumber] = [0.0,0.8,1.0]
 */
static func setGradient(viewWithGradient: UIView, backgroundColor: UIColor, gradientColors: [CGColor], locations:[NSNumber], boundsOfGradient:CGRect) {

    if gradientColors.count != locations.count {
        print("gradientColors and locations must have same size!")
        return
    }

    viewWithGradient.backgroundColor = backgroundColor
    let mask = CAGradientLayer()
    mask.colors = gradientColors
    mask.locations = locations
    mask.frame = boundsOfGradient
    viewWithGradient.layer.mask = mask
}

Call like this像这样打电话

    let gradientColors = [UIColor.red.cgColor,UIColor.blue.cgColor,UIColor.yellow.cgColor]
    let locations:[NSNumber] = [0.0,0.8,1.0]
    GeneralTools.setGradient(viewWithGradient: yourViewThatShouldGetGradient, backgroundColor: backgroundColorOfYourViewWithGradient, gradientColors: gradientColors, locations: locations, boundsOfGradient: viewWhereIsYourGradientInside.bounds)

Maybe not clear enough boundsOfGradient : The bounds will be set to your gradients frame.也许不够清楚boundsOfGradient :边界将设置为您的渐变框架。 So simply said this will declare the size of your gradient.所以简单地说这将声明你的渐变的大小。

gmoraleda's answer is correct. gmoraleda 的答案是正确的。 Do this on viewDidLayoutSubviews if you're using AutoLayout.如果您使用 AutoLayout,请在viewDidLayoutSubviews上执行此操作。

The code works fine.该代码工作正常。 However, you should call it at layoutSubviews .但是,您应该在layoutSubviews调用它。

Swift 5斯威夫特 5

class ViewExample: UIView {

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

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        configureGradientLayer()
    }

    func configureGradientLayer(){
        backgroundColor = .clear
        let gradient = CAGradientLayer()
        gradient.colors = [UIColor.systemPurple.cgColor, UIColor.systemPink.cgColor]
        gradient.locations = [0, 1]
        gradient.frame = bounds
        layer.addSublayer(gradient)
    }

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM