Why gradient doesn't cover the whole width of the view

后端 未结 4 704
孤街浪徒
孤街浪徒 2021-01-05 19:44

I\'m trying to apply a gradient to a view which is constraint to the top, left and right of the main screen but for some reason the gradient doesn\'t cover the whole width o

相关标签:
4条回答
  • 2021-01-05 20:02

    You can simplify it by CustomClass with one line of code

    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)
    
    0 讨论(0)
  • 2021-01-05 20:14

    You needn't set the start and end point, given your goal is to have the gradient span the entire view. You're already setting that with `

    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)
        }
    }
    
    0 讨论(0)
  • 2021-01-05 20:19

    The problem is likely that you are adding the gradient layer in viewDidLoad(). A view doesn't get set to it's final size until after viewDidLoad().

    Your view controller may be set up in your XIB/Storyboard for a different screen-size than you're running it on. (Say you have it set to iPhone SE size, but you're running it on a 6. The 6's screen is a little wider, so the layer will get set to the width of the iPhone SE, when the view is first loaded. Then the view will be resized, but the layer's size will never be adjusted.)

    You should implement the UIViewController method viewDidLayoutSubviews(), and in that method, adjust the layer's frame:

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

    That way if the view gets resized (due to auto-rotation, for example) the gradient layer will be automatically adjusted accordingly.

    EDIT:

    As pointed out by Sulthan, changes to a layer's frame are animated by default. You should probably wrap the frame change in a CATransaction.begin/CATransaction.end and disable actions, like below:

    override func viewDidLayoutSubviews() {
      CATransaction.begin()
      CATransaction.setDisableActions(true)
      gradientLayer.frame = self.view.bounds
      CATransaction.commit()
    }
    
    0 讨论(0)
  • 2021-01-05 20:22

    You can turn it to a UIView. So it will resize automatically and can be seen directly in the Storyboard:

    @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
        }
    }
    

    0 讨论(0)
提交回复
热议问题