14

I extended UIView to add a addGradientWithColor() method to get the gradient background:

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

My issue is when I run landscape mode, the UIView is not stretched

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

I tried to calling viewDidLayoutSubviews() but its not working properly

Here is the screen shot:

after removing viewDidLayoutSubviews() enter image description here

kb920
  • 3,039
  • 2
  • 33
  • 44
Aravind
  • 1,080
  • 2
  • 12
  • 18

4 Answers4

26

You can subclass the UIView and override drawRect method where you add your gradient.

Updated to 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)
        }
    }
}

After you create your UIView you just need to add your constraints to that view.

TomCobo
  • 2,886
  • 3
  • 25
  • 43
6

you could save a reference to the layer, and adjust it's frame in the views layoutSublayersOfLayer method. this could be outsourced in an UIView subclass:

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
}
}
Bryan Bryce
  • 1,310
  • 1
  • 16
  • 29
dalipsia
  • 186
  • 1
  • 7
3

Layers do not autoresize them self. To fix this issue you should change layer frame. This is one way how it is possible to implement:

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

 }
Oleg Gordiichuk
  • 15,240
  • 7
  • 60
  • 100
  • 1
    in my case after adding viewdidlayoutsubviews() method. I am getting two gradient views in the same view. I attached the screenshot in the question itself – Aravind Sep 19 '16 at 13:18
2

Inspired from solutions here, I've created the following class.

Usage examples:

// 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)

The class:

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:)") }
}
Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100