为什么渐变不会覆盖视图的整个宽度

时间:2017-06-24 14:09:05

标签: ios swift

我正在尝试将渐变应用于主视图的顶部,左侧和右侧约束的视图,但由于某种原因,渐变不会覆盖应用于视图的整个宽度(请参阅图中的黄色。)

class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let gradient = CAGradientLayer()
        gradient.colors = [UIColor.blue.cgColor, UIColor.white.cgColor]
        gradient.startPoint = CGPoint(x:00, y:00)
        gradient.endPoint = CGPoint(x:0, y:0.6)
        gradient.frame = myView.bounds
        myView.clipsToBounds = true
        myView.layer.insertSublayer(gradient, at: 0)
    }
}

我做错了什么?

enter image description here

4 个答案:

答案 0 :(得分:18)

问题可能是您在viewDidLoad()中添加了渐变图层。在viewDidLoad()之后,视图不会设置为最终大小。

您的视图控制器可能会在您的XIB / Storyboard中设置,其屏幕尺寸与您在其上运行时不同。 (假设您已将其设置为iPhone SE大小,但您在6上运行它.6的屏幕稍微宽一点,因此图层将设置为iPhone SE的宽度,首先加载视图。然后将调整视图大小,但不会调整图层的大小。)

您应该实现UIViewController方法viewDidLayoutSubviews(),并在该方法中调整图层的框架:

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

这样,如果视图调整大小(例如,由于自动旋转),渐变图层将相应地自动调整。

编辑:

正如Sulthan所指出的,默认情况下,对图层框架的更改是动画的。您应该将框架更改换成CATransaction.begin / CATransaction.end并禁用操作,如下所示:

override func viewDidLayoutSubviews() {
  CATransaction.begin()
  CATransaction.setDisableActions(true)
  gradientLayer.frame = self.view.bounds
  CATransaction.commit()
}

答案 1 :(得分:1)

您的目标是让渐变跨越整个视图,您无需设置起点和终点。你已经用`

设置了它
gradientLayer.frame = self.view.bounds

`

import UIKit
class ViewController: UIViewController {

    @IBOutlet weak var myView: UIView!
    var gradientLayer: CAGradientLayer!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        createGradientLayer()
    }

    func createGradientLayer() {
        gradientLayer = CAGradientLayer()

        gradientLayer.frame = self.view.bounds

        gradientLayer.colors = [UIColor.blueColor().CGColor, UIColor.whiteColor().CGColor]

        self.view.layer.addSublayer(gradientLayer)
    }
}

答案 2 :(得分:0)

您可以通过CustomClass用一行代码对其进行简化

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


// MARK: Usage

@IBOutlet weak var myView: GradientView!

guard let gradientLayer = myView.layer as? CAGradientLayer else { return }
gradient.colors = [UIColor.blue.cgColor, UIColor.white.cgColor]
gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
gradient.endPoint = CGPoint(x:0, y:0.6)

答案 3 :(得分:0)

您可以将其变成UIView。因此它将自动调整大小,并可以直接在情节提要中查看:

@IBDesignable
final class GradientView: UIView {

    @IBInspectable var firstColor: UIColor = .clear { didSet { updateView() } }
    @IBInspectable var secondColor: UIColor = .clear { didSet { updateView() } }

    @IBInspectable var startPoint: CGPoint = CGPoint(x: 0, y: 0) { didSet { updateView() } }
    @IBInspectable var endPoint: CGPoint = CGPoint(x: 1, y: 1) { didSet { updateView() } }

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

    override func layoutSubviews() {
        super.layoutSubviews()
        updateView()
        layer.frame = bounds
    }

    private func updateView() {
        let layer = self.layer as! CAGradientLayer
        layer.colors = [firstColor, secondColor].map {$0.cgColor}
        layer.startPoint = startPoint
        layer.endPoint = endPoint
    }
}

Preview