UIView 和屏幕旋转上的对角渐变背景

Diagonal Gradient background on UIView and Screen Rotation

我正在尝试将 UIView 的背景设置为渐变。我的 UIViewControllerviewDidLoad 方法中有以下内容:

let gradientLayer = CAGradientLayer()
gradientLayer.colors = [UIColor.blue70.cgColor, UIColor.blue60.cgColor, UIColor.blue70.cgColor]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1 )
gradientLayer.frame = self.view.bounds

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

渐变按预期呈现。但是,当我旋转设备时,渐变不会重绘并且不再正确呈现。从肖像->风景旋转给我留下了右边或左边的空白部分。从风景->肖像旋转给我留下了底部的空白部分。我尝试将此代码移至 viewDidLayoutSubviews,但这并没有解决问题。关于如何完成此操作的任何建议?

我在这里推荐的是在 viewWillLayoutSubviews() 方法中添加渐变

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    self.view.addGradiant()
}

但是现在我们必须删除旧层当添加新层和新帧时(以防 Phone 旋转)

然后我们可以先删除图层并添加新图层,就像在这个扩展方法中一样

extension UIView {

func addGradiant() {
    let GradientLayerName = "gradientLayer"

    if let oldlayer = self.layer.sublayers?.filter({[=11=].name == GradientLayerName}).first {
        oldlayer.removeFromSuperlayer()
    }

    let gradientLayer = CAGradientLayer()
    gradientLayer.colors = [UIColor.blue.cgColor, UIColor.red.cgColor, UIColor.green.cgColor]
    gradientLayer.startPoint = CGPoint(x: 0, y: 0)
    gradientLayer.endPoint = CGPoint(x: 1, y: 1 )
    gradientLayer.frame = self.bounds
    gradientLayer.name = GradientLayerName

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

}

制作 gradientLayer 视图控制器的 属性.

let gradientLayer = CAGradientLayer()

按照与您相同的方式在 viewDidLoad 中添加 gradientLayer。

在 viewWillLayoutSubviews 中设置框架

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    gradientLayer.frame = self.view.bounds
}

虽然您可以按照其他答案的建议进行操作并更新 viewDidLayoutSubviews 中的渐变层边界,但更可重用的方法是制作一个渐变视图 subclass 谁是 layerClass 是一个 CAGradientLayer。这样的视图将自动调整其层的大小以适合视图(因为渐变层现在是视图的后备层而不是某些子层)并且您只需更改视图的 class 即可在任何地方使用此视图在您的 nib 文件或情节提要中:

class GradientView: UIView {
    var colors: [UIColor] = [.red, .white] {
        didSet {
            setup()
        }
    }
    var locations: [CGFloat] = [0,1] {
        didSet {
            setup()
        }
    }
    var startPoint: CGPoint = .zero  {
        didSet {
            setup()
        }
    }
    var endPoint: CGPoint = CGPoint(x: 1, y: 1) {
        didSet {
            setup()
        }
    }

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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        setup()
    }
    private func setup() {
        guard let layer = self.layer as? CAGradientLayer else {
            return
        }
        layer.colors = colors.map { [=10=].cgColor }
        layer.locations = locations.map { NSNumber(value: Double([=10=])) }
        layer.startPoint = startPoint
        layer.endPoint = endPoint
    }
}