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

Posted

技术标签:

【中文标题】使用自动布局为 UIView 应用渐变背景【英文标题】:Applying gradient background for UIView using auto layout 【发布时间】:2016-09-19 12:17:39 【问题描述】:

我扩展了 UIView 添加了 addGradientWithColor() 方法来获取渐变背景:

 extension UIView 
   func addGradientWithColor() 
     let gradient = CAGradientLayer()
     gradient.frame = self.bounds
     gradient.colors = [gradientEndColor.CGColor,  gradientStartColor.CGColor]
     gradient.startPoint = CGPointMake(1,0)
     gradient.endPoint = CGPointMake(0.2,1)
    self.layer.insertSublayer(gradient, atIndex: 0)
    

我的问题是当我运行横向模式时,UIView 没有被拉伸

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    self.view.addGradientWithColor() 

我尝试调用 viewDidLayoutSubviews() 但它无法正常工作

这是屏幕截图:

删除 viewDidLayoutSubviews() 后

【问题讨论】:

你检查过这个ios8-auto-layout-and-gradient 为什么你不继承 UIView 并覆盖 drawRect 方法。在该方法中,只需添加渐变。然后在 UIView 中添加您需要的约束即可。 @rob180 谢谢。是的,但没有解决我的问题 @tomCobo 谢谢你的建议,我会试试的 @tomCobo 谢谢你的建议是最好的。请给它作为答案 【参考方案1】:

您可以继承 UIView 并覆盖添加渐变的 drawRect 方法。

更新到 Swift 4


class GradientView: UIView 

    private let gradient : CAGradientLayer = CAGradientLayer()
    private let gradientStartColor: UIColor
    private let gradientEndColor: UIColor

    init(gradientStartColor: UIColor, gradientEndColor: UIColor) 
        self.gradientStartColor = gradientStartColor
        self.gradientEndColor = gradientEndColor
        super.init(frame: .zero)
    

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

    override func layoutSublayers(of layer: CALayer) 
        super.layoutSublayers(of: layer)
        gradient.frame = self.bounds
    

    override public func draw(_ rect: CGRect) 
        gradient.frame = self.bounds
        gradient.colors = [gradientEndColor.cgColor, gradientStartColor.cgColor]
        gradient.startPoint = CGPoint(x: 1, y: 0)
        gradient.endPoint = CGPoint(x: 0.2, y: 1)
        if gradient.superlayer == nil 
            layer.insertSublayer(gradient, at: 0)
        
    

创建 UIView 后,您只需将约束添加到该视图。

【讨论】:

我要加if (!self.gradient.superlayer) self.layer.insertSublayer(self.gradient, atIndex: 0) if self.gradient.superlayer != nil 应该是if self.gradient.superlayer == nil 确定是的。谢谢@thijsonline UIColor 对我不起作用,我不得不改用 CGColor。【参考方案2】:

您可以保存对图层的引用,并在视图layoutSublayersOfLayer 方法中调整它的框架。这可以在 UIView 子类中外包:

class GradientView: UIView 

private let gradient : CAGradientLayer = CAGradientLayer()

/**
 displays a gradient on the view
 */
func addGradient() 

    self.gradient.frame     = self.bounds
    self.gradient.colors    = [gradientEndColor.CGColor, gradientStartColor.CGColor]
    gradient.startPoint     = CGPointMake(1,0)
    gradient.endPoint       = CGPointMake(0.2,1)        
    self.layer.insertSublayer(self.gradient, atIndex: 0)


/**
 resizes the gradient with the view size
 */
override func layoutSublayers(of layer: CALayer) 
    super.layoutSublayers(of: layer)
    self.gradient.frame = self.bounds


【讨论】:

【参考方案3】:

图层不会自行自动调整大小。要解决此问题,您应该更改图层框架。这是一种实现方式:

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    //Update you're layer based on the new frame
    self.view.addGradientWithColor()

 

【讨论】:

在我的情况下添加了 viewdidlayoutsubviews() 方法。我在同一个视图中得到两个渐变视图。我在问题本身中附上了屏幕截图【参考方案4】:

受此处解决方案的启发,我创建了以下类。

用法示例:

// Simple usage. From clear to black.
let gradientView1 = GradientView(colors: [.clear, .black])

// Tweak locations. Here the gradient from red to green will take 30% of the view.
let gradientView2 = GradientView(colors: [.red, .green, .blue], locations: [0, 0.3, 1])

// Create your own gradient.
let gradient = CAGradientLayer()
gradient.colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
let gradientView3 = GradientView(gradient: gradient)

班级:

import UIKit

/**
 * View with a gradient layer.
 */
class GradientView: UIView 

    let gradient : CAGradientLayer

    init(gradient: CAGradientLayer) 
        self.gradient = gradient
        super.init(frame: .zero)
        self.gradient.frame = self.bounds
        self.layer.insertSublayer(self.gradient, at: 0)
    

    convenience init(colors: [UIColor], locations:[Float] = [0.0, 1.0]) 
        let gradient = CAGradientLayer()
        gradient.colors = colors.map  $0.cgColor 
        gradient.locations = locations.map  NSNumber(value: $0) 
        self.init(gradient: gradient)
    

    override func layoutSublayers(of layer: CALayer) 
        super.layoutSublayers(of: layer)
        self.gradient.frame = self.bounds
    

    required init?(coder: NSCoder)  fatalError("no init(coder:)") 

【讨论】:

以上是关于使用自动布局为 UIView 应用渐变背景的主要内容,如果未能解决你的问题,请参考以下文章

Swift:UIView 的背景渐变

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

如何创建像 Instagram 应用一样的动画背景渐变?

如何在 UIView 上应用不透明度渐变?

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

向 Xamarin Forms Visual Studio 中的布局添加渐变背景