Swift:UIView 的背景渐变

Posted

技术标签:

【中文标题】Swift:UIView 的背景渐变【英文标题】:Swift: Background gradient for UIView 【发布时间】:2018-04-26 07:25:11 【问题描述】:

我在尝试将渐变背景添加到 UIView 时遇到问题。我制作了UIViewextension 并添加了以下方法:

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

    layer.insertSublayer(gradientLayer, at: 0)

然后我打电话:

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

但它不起作用。视图已呈现,但其背景完全清晰。我也试过CGColor

【问题讨论】:

试试这个,github.com/matvdg/Gradient-View 代码工作正常,检查其余代码 【参考方案1】:

有两个问题:

我需要设置起点和终点以提供渐变方向:

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)

第二个问题是CAGradientLayer在视图布局后生效。我解决了在viewDidAppear 上调用setGradientBackground() 的问题:

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

【讨论】:

为什么你实际上接受了你的答案,而不是 Moayad 的?好像他回答得更快了。 第二个问题:实际上是因为视图几何是在调用 viewDidAppear(_:) 时设置的。您可以并且可能应该在其他地方调用 setGradientBackground(colorTop:colorBottom:),例如 viewDidLoad(),否则您可能会添加多个渐变层。您只需确保在 viewDidLayoutSubviews() 中设置几何图形时更新渐变层框架。【参考方案2】:

将您的方法更新为代码打击:

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)

【讨论】:

【参考方案3】:

Moayad 的回答对我来说效果最好,但它以顶部颜色为底部,所以我颠倒了他发布的功能。

斯威夫特 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)

【讨论】:

【参考方案4】:

对于@IBDesignable:您可以在情节提要上自定义您的 UI。它更易于使用。

@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
    

【讨论】:

您好,能否请您解释一下如何设置 Start X、start Y、End X 和 End Y。???【参考方案5】:

这确实适用于我的项目

/**
 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

这样打电话

    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)

可能不够清楚boundsOfGradient:边界将设置为您的渐变框架。所以简单地说这将声明你的渐变的大小。

【讨论】:

【参考方案6】:

gmoraleda 的回答是正确的。如果您使用的是 AutoLayout,请在 viewDidLayoutSubviews 上执行此操作。

【讨论】:

【参考方案7】:

代码运行良好。但是,您应该致电layoutSubviews

斯威夫特 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)
    

【讨论】:

以上是关于Swift:UIView 的背景渐变的主要内容,如果未能解决你的问题,请参考以下文章

text Swift - 设置UIView的渐变颜色

如何在 Swift 4 的 UIView 中创建带圆角的渐变边框

UIView 背景渐变与界面生成器视图

使用自动布局为 UIView 应用渐变背景

在“集合视图”单元格中的UIView上设置渐变背景

使用 CAGradientLayer 类更改 UiView IOS 的渐变背景图层颜色