Search code examples
iosswift4cagradientlayer

How to add gradient layer which fills the view frame exactly


In my app i'm adding the gradient layer to UIView and UIToolBar but it doesn't fill the views exactly enter image description hereenter image description here

    let gradient:CAGradientLayer = CAGradientLayer()
    gradient.frame               =  self.vw_gradientForToolBar.bounds
    gradient.colors              = [hexStringToUIColor(hex: "#5d8f32").cgColor,hexStringToUIColor(hex: "#04667f").cgColor]
    gradient.startPoint = CGPoint(x: 0, y: 0)
    gradient.endPoint = CGPoint(x: 0.5, y: 0)

    UIGraphicsBeginImageContextWithOptions(CGSize(width: 1, height: 1), false, 0.0)
    let img : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    self.toolBar.setBackgroundImage(img, forToolbarPosition: .any, barMetrics: .default)
    vw_gradientForToolBar.layer.addSublayer(gradient)

View Hirarchy

enter image description here

enter image description here


Solution

  • It's a little tough to tell exactly what you have going on, based on the images you posted, however... This may simplify things for you.

    First, keep in mind that Layers do not auto-scale, so when your tool bar changes size (different devices, device rotation, etc), you want your gradient layer to also resize. Best way to do that is to use a UIView subclass and override layoutSubviews().

    So, add this class to your code:

    class GradientView: UIView {
    
        override class var layerClass: AnyClass {
            return CAGradientLayer.self
        }
    
        override func layoutSubviews() {
            let gradientLayer = layer as! CAGradientLayer
            gradient.colors = [hexStringToUIColor(hex: "#5d8f32").cgColor,hexStringToUIColor(hex: "#04667f").cgColor]
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 0.5, y: 0)
        }
    
    }
    

    Then in your controller's viewDidLoad() function:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        let vwGrad = GradientView()
        vwGrad.frame = toolBar.frame
        vwGrad.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.toolBar.insertSubview(vwGrad, at: 0)
    
    }
    

    Note: you would no longer need your vw_gradientForToolBar (which, I'm assuming, is a UIView connected via @IBOutlet).