I'm trying to generate a view with a gradient color background (A solid color to transparent) at runtime. Is there a way of doing that?
-
2This is a helpful little tool that creates gradient code for you https://itunes.apple.com/gb/app/gradient-creator/id1031070259?mt=12 – burrGGG Sep 01 '15 at 18:54
-
Creating Gradient Colors Using CAGradientLayer https://www.appcoda.com/cagradientlayer/ – Max Apr 18 '19 at 07:52
22 Answers
Objective-C:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = @[(id)[UIColor whiteColor].CGColor, (id)[UIColor blackColor].CGColor];
[view.layer insertSublayer:gradient atIndex:0];
Swift:
let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.white.cgColor, UIColor.black.cgColor]
view.layer.insertSublayer(gradient, at: 0)
Info: use startPoint and endPoint to change direction of gradient.
If there are any other views added onto this UIView
(such as a UILabel
), you may want to consider setting the background color of those UIView
’s to [UIColor clearColor]
so the gradient view is presented instead of the background color for sub views. Using clearColor
has a slight performance hit.

- 1
- 1

- 17,418
- 8
- 58
- 76
-
14+1 for shortest amount of code out of all solutions. I just added to my existing view controller, changed the 2 refs to `view` to `self.view` and it worked like a charm :) – Ergin Aug 01 '14 at 04:01
-
4Also relevant is where to add this code. I needed the following post to get this to work: http://stackoverflow.com/a/20059268/1480518 – Garrett Disco Dec 08 '14 at 22:51
-
14
-
54Don't forget to use 'startPoint' and 'endPoint' to change gradient direction. Default values are (0.5, 0) and (0.5,1) - from top to bottom direction. – Valentin Shamardin Jul 10 '15 at 21:37
-
15When my UIView is using AutoLayout, I also had to call `gradient.frame = view.bounds` in `viewDidAppear()` and in `didRotateFromInterfaceOrientation()` or else the gradient wouldn't be sized properly. – EricRobertBrewer Aug 25 '16 at 00:06
-
-
How do you set the gradient to have colorA take 20% of the view and color to take the other 80%? – PLOW Oct 18 '16 at 14:55
-
Fantastic ... though to be noted, you must add "view" to self.view (or another container) as a subview ... so I renamed "view" to something more understandable like "gradientContainer" – Chris Allinson Feb 27 '17 at 17:12
-
1
-
In my case, since I had a crash, I replaced this line `view.layer.insertSublayer(gradient, at: 0)` with `view.layer.addSublayer(gradient)` – Reza Dehnavi Dec 02 '20 at 08:22
You can create a custom class GradientView
:
Swift 5
class GradientView: UIView {
override open class var layerClass: AnyClass {
return CAGradientLayer.classForCoder()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let gradientLayer = layer as! CAGradientLayer
gradientLayer.colors = [UIColor.white.cgColor, UIColor.black.cgColor]
}
}
In the storyboard, set the class type to any view that you want to have gradient background:
This is better in the following ways:
- No need to set frame of
CLayer
- Use
NSConstraint
as usual on theUIView
- Don't need to create sublayers (less memory use)

- 30,852
- 26
- 164
- 234
-
1On Swift 3 the `layerClass` is no longer a function, it's a property so you have to override it like a property: http://stackoverflow.com/questions/28786597/overriding-properties-in-swift. Also you have to implement `override init(frame: CGRect)`, check this answer: http://stackoverflow.com/questions/27374330/ibdesignable-error-ib-designables-failed-to-update-auto-layout-status-interf. Thanks! – LaloLoop Sep 19 '16 at 17:13
-
Hello @LaloLoop, thanks for the comment! I've updated the code. I don't think I have to override `init(frame:CGRect)` though. I tested the updated code and it works fine. – Yuchen Sep 29 '16 at 12:24
-
@Yuchen Zhong It crashing in IB, but works in the app. Any reasons why it is not rendered in IB if `@IBDesignable` is used? – Alexander Volkov Mar 13 '18 at 03:57
-
@AlexanderVolkov Probably some other issue? We've been using it like so in the storyboard and don't seem to have any problem though. You can debug your storyboard and see which line is crashing it. – Yuchen Mar 13 '18 at 12:34
-
1
-
@AlexanderVolkov It is unfortunately not well-documented, but `@IBDesignable` classes must implement `init(frame:)` or they will crash in IB. – idrougge Jul 12 '21 at 16:35
-
Try This it worked like a charm for me,
Objective C
I have set RGB gradient background Color to UIview
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,35)];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.startPoint = CGPointZero;
gradient.endPoint = CGPointMake(1, 1);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:34.0/255.0 green:211/255.0 blue:198/255.0 alpha:1.0] CGColor],(id)[[UIColor colorWithRed:145/255.0 green:72.0/255.0 blue:203/255.0 alpha:1.0] CGColor], nil];
[view.layer addSublayer:gradient];
UPDATED :- Swift3 +
Code :-
var gradientView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 35))
let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame.size = self.gradientView.frame.size
gradientLayer.colors =
[UIColor.white.cgColor,UIColor.red.withAlphaComponent(1).cgColor]
//Use diffrent colors
gradientView.layer.addSublayer(gradientLayer)
You can add starting and end point of gradient color.
gradientLayer.startPoint = CGPoint(x: 0.0, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
For more details description refer CAGradientLayer Doc
Hope this is help for some one .

- 5,941
- 2
- 44
- 55
This is my recommended approach.
To promote reusability, I'd say create a category of CAGradientLayer
and add your desired gradients as class methods. Specify them in the header
file like this :
#import <QuartzCore/QuartzCore.h>
@interface CAGradientLayer (SJSGradients)
+ (CAGradientLayer *)redGradientLayer;
+ (CAGradientLayer *)blueGradientLayer;
+ (CAGradientLayer *)turquoiseGradientLayer;
+ (CAGradientLayer *)flavescentGradientLayer;
+ (CAGradientLayer *)whiteGradientLayer;
+ (CAGradientLayer *)chocolateGradientLayer;
+ (CAGradientLayer *)tangerineGradientLayer;
+ (CAGradientLayer *)pastelBlueGradientLayer;
+ (CAGradientLayer *)yellowGradientLayer;
+ (CAGradientLayer *)purpleGradientLayer;
+ (CAGradientLayer *)greenGradientLayer;
@end
Then in your implementation file, specify each gradient with this syntax :
+ (CAGradientLayer *)flavescentGradientLayer
{
UIColor *topColor = [UIColor colorWithRed:1 green:0.92 blue:0.56 alpha:1];
UIColor *bottomColor = [UIColor colorWithRed:0.18 green:0.18 blue:0.18 alpha:1];
NSArray *gradientColors = [NSArray arrayWithObjects:(id)topColor.CGColor, (id)bottomColor.CGColor, nil];
NSArray *gradientLocations = [NSArray arrayWithObjects:[NSNumber numberWithInt:0.0],[NSNumber numberWithInt:1.0], nil];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = gradientColors;
gradientLayer.locations = gradientLocations;
return gradientLayer;
}
Then simply import this category in your ViewController
or any other required subclass
, and use it like this :
CAGradientLayer *backgroundLayer = [CAGradientLayer purpleGradientLayer];
backgroundLayer.frame = self.view.frame;
[self.view.layer insertSublayer:backgroundLayer atIndex:0];

- 1,442
- 19
- 35
-
where should you put the code to use it? what lifecycle method? viewdidappear makes it appear a second too late. viewdidload and viewdidappear cause it to not work while rotating. viewdidlayoutsubviews works better for rotation but still ends up looking a little choppy. – Adam Johns Aug 04 '14 at 19:20
-
-
1When i put it in `viewDidLoad`, it didn't work if the app was launched in landscape orientation. My solution was to make the background layer frame wider than the view.frame to compensate for other orientations. – Adam Johns Aug 05 '14 at 13:47
-
2viewDidLoad works, you just have to also set the AutoResizingMask using [backgroundLayer setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; – ekscrypto Mar 29 '17 at 19:39
extension UIView {
func applyGradient(isVertical: Bool, colorArray: [UIColor]) {
layer.sublayers?.filter({ $0 is CAGradientLayer }).forEach({ $0.removeFromSuperlayer() })
let gradientLayer = CAGradientLayer()
gradientLayer.colors = colorArray.map({ $0.cgColor })
if isVertical {
//top to bottom
gradientLayer.locations = [0.0, 1.0]
} else {
//left to right
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
}
backgroundColor = .clear
gradientLayer.frame = bounds
layer.insertSublayer(gradientLayer, at: 0)
}
}
USAGE
someView.applyGradient(isVertical: true, colorArray: [.green, .blue])

- 8,381
- 2
- 55
- 49
Since I only needed one type of gradient throughout my app I created a subclass of UIView and preconfigured the gradient layer on initialization with fixed colors. The initializers of UIView call the configureGradientLayer-method, which configures the CAGradientLayer:
DDGradientView.h:
#import <UIKit/UIKit.h>
@interface DDGradientView : UIView {
}
@end
DDGradientView.m:
#import "DDGradientView.h"
@implementation DDGradientView
// Change the views layer class to CAGradientLayer class
+ (Class)layerClass
{
return [CAGradientLayer class];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self) {
[self configureGradientLayer];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if(self) {
[self configureGradientLayer];
}
return self;
}
// Make custom configuration of your gradient here
- (void)configureGradientLayer {
CAGradientLayer *gLayer = (CAGradientLayer *)self.layer;
gLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor lightGrayColor] CGColor], nil];
}
@end

- 351
- 2
- 6
-
The method name`initGradientLayer` is similar to an initializer. I don't think it's very suitable. – DawnSong Sep 20 '16 at 15:12
-
I've extended the accepted answer a little using Swift's extension functionality as well as an enum.
Oh and if you are using Storyboard like I do, make sure to call gradientBackground(from:to:direction:)
in viewDidLayoutSubviews()
or later.
Swift 3
enum GradientDirection {
case leftToRight
case rightToLeft
case topToBottom
case bottomToTop
}
extension UIView {
func gradientBackground(from color1: UIColor, to color2: UIColor, direction: GradientDirection) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [color1.cgColor, color2.cgColor]
switch direction {
case .leftToRight:
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
case .rightToLeft:
gradient.startPoint = CGPoint(x: 1.0, y: 0.5)
gradient.endPoint = CGPoint(x: 0.0, y: 0.5)
case .bottomToTop:
gradient.startPoint = CGPoint(x: 0.5, y: 1.0)
gradient.endPoint = CGPoint(x: 0.5, y: 0.0)
default:
break
}
self.layer.insertSublayer(gradient, at: 0)
}
}

- 353
- 2
- 12
-
This applies to every solution but just a reminder that self.clipsToBounds needs to be true or gradient.cornerRadius needs to be set to self.layer.cornerRadius if self has rounded corners. – Gary Z Dec 02 '20 at 08:59
Swift Implementation:
var gradientLayerView: UIView = UIView(frame: CGRectMake(0, 0, view.bounds.width, 50))
var gradient: CAGradientLayer = CAGradientLayer()
gradient.frame = gradientLayerView.bounds
gradient.colors = [UIColor.grayColor().CGColor, UIColor.clearColor().CGColor]
gradientLayerView.layer.insertSublayer(gradient, atIndex: 0)
self.view.layer.insertSublayer(gradientLayerView.layer, atIndex: 0)

- 3,912
- 2
- 16
- 19

- 121
- 1
- 3
I have implemented this in swift with an extension:
Swift 3
extension UIView {
func addGradientWithColor(color: UIColor) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [UIColor.clear.cgColor, color.cgColor]
self.layer.insertSublayer(gradient, at: 0)
}
}
Swift 2.2
extension UIView {
func addGradientWithColor(color: UIColor) {
let gradient = CAGradientLayer()
gradient.frame = self.bounds
gradient.colors = [UIColor.clearColor().CGColor, color.CGColor]
self.layer.insertSublayer(gradient, atIndex: 0)
}
}
No I can set a gradient on every view like this:
myImageView.addGradientWithColor(UIColor.blue)

- 189
- 7

- 3,590
- 4
- 29
- 40
-
Swift3 call must be like : myImageView.addGradientWithColor(color: UIColor.blue) – MGY Nov 17 '16 at 07:01
A Swift Approach
This answer builds on the answers above and provides implementation for dealing with the problem of the gradient not being properly applied during rotation. It satisfies this problem by changing the gradient layer to a square so that rotation in all directions results in a correct gradient. The function signature includes a Swift variadic argument that allows one to pass in as many CGColorRef's (CGColor) as needed (see sample usage). Also provided is an example as a Swift extension so that one can apply a gradient to any UIView.
func configureGradientBackground(colors:CGColorRef...){
let gradient: CAGradientLayer = CAGradientLayer()
let maxWidth = max(self.view.bounds.size.height,self.view.bounds.size.width)
let squareFrame = CGRect(origin: self.view.bounds.origin, size: CGSizeMake(maxWidth, maxWidth))
gradient.frame = squareFrame
gradient.colors = colors
view.layer.insertSublayer(gradient, atIndex: 0)
}
To use:
in viewDidLoad...
override func viewDidLoad() {
super.viewDidLoad()
configureGradientBackground(UIColor.redColor().CGColor, UIColor.whiteColor().CGColor)
}
Extension implementation
extension CALayer {
func configureGradientBackground(colors:CGColorRef...){
let gradient = CAGradientLayer()
let maxWidth = max(self.bounds.size.height,self.bounds.size.width)
let squareFrame = CGRect(origin: self.bounds.origin, size: CGSizeMake(maxWidth, maxWidth))
gradient.frame = squareFrame
gradient.colors = colors
self.insertSublayer(gradient, atIndex: 0)
}
}
Extension use-case example:
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.configureGradientBackground(UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor, UIColor.whiteColor().CGColor)
}
Which means the gradient background can now be applied to any UIControl since all controls are UIViews (or a subclass) and all UIViews have CALayers.
Swift 4
Extension implementation
extension CALayer {
public func configureGradientBackground(_ colors:CGColor...){
let gradient = CAGradientLayer()
let maxWidth = max(self.bounds.size.height,self.bounds.size.width)
let squareFrame = CGRect(origin: self.bounds.origin, size: CGSize(width: maxWidth, height: maxWidth))
gradient.frame = squareFrame
gradient.colors = colors
self.insertSublayer(gradient, at: 0)
}
}
Extension use-case example:
override func viewDidLoad() {
super.viewDidLoad()
self.view.layer.configureGradientBackground(UIColor.purple.cgColor, UIColor.blue.cgColor, UIColor.white.cgColor)
}

- 5,988
- 6
- 48
- 75

- 12,895
- 5
- 82
- 100
What you are looking for is CAGradientLayer
. Every UIView
has a layer - into that layer you can add sublayers, just as you can add subviews. One specific type is the CAGradientLayer
, where you give it an array of colors to gradiate between.
One example is this simple wrapper for a gradient view:
http://oleb.net/blog/2010/04/obgradientview-a-simple-uiview-wrapper-for-cagradientlayer/
Note that you need to include the QuartZCore framework in order to access all of the layer parts of a UIView.

- 74,769
- 26
- 128
- 150
Its a good idea to call the solutions above to update layer on the
viewDidLayoutSubviews
to get the views updated correctly

- 1,329
- 20
- 24
Swift 4:
Shows gradient in IB correctly:
@IBDesignable public class GradientView: UIView {
override open class var layerClass: AnyClass {
return CAGradientLayer.classForCoder()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configureGradientLayer()
}
public override init(frame: CGRect) {
super.init(frame: frame)
configureGradientLayer()
}
func configureGradientLayer() {
let gradientLayer = layer as! CAGradientLayer
gradientLayer.colors = [UIColor(hex: 0x003399).cgColor, UIColor(hex: 0x00297b).cgColor]
}
}

- 7,904
- 1
- 47
- 44
Simple swift view based on Yuchen's version
class GradientView: UIView {
override class func layerClass() -> AnyClass { return CAGradientLayer.self }
lazy var gradientLayer: CAGradientLayer = {
return self.layer as! CAGradientLayer
}()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Then you can use gradientLayer after initialization like this...
someView.gradientLayer.colors = [UIColor.whiteColor().CGColor, UIColor.blackColor().CGColor]
My solution is to create UIView
subclass with CAGradientLayer
accessible as a readonly property. This will allow you to customize your gradient how you want and you don't need to handle layout changes yourself. Subclass implementation:
@interface GradientView : UIView
@property (nonatomic, readonly) CAGradientLayer *gradientLayer;
@end
@implementation GradientView
+ (Class)layerClass
{
return [CAGradientLayer class];
}
- (CAGradientLayer *)gradientLayer
{
return (CAGradientLayer *)self.layer;
}
@end
Usage:
self.iconBackground = [GradientView new];
[self.background addSubview:self.iconBackground];
self.iconBackground.gradientLayer.colors = @[(id)[UIColor blackColor].CGColor, (id)[UIColor whiteColor].CGColor];
self.iconBackground.gradientLayer.startPoint = CGPointMake(1.0f, 1.0f);
self.iconBackground.gradientLayer.endPoint = CGPointMake(0.0f, 0.0f);

- 5,660
- 4
- 45
- 58
SWIFT 3
To add a gradient layer on your view
Bind your view outlet
@IBOutlet var YOURVIEW : UIView!
Define the CAGradientLayer()
var gradient = CAGradientLayer()
Here is the code you have to write in your viewDidLoad
YOURVIEW.layoutIfNeeded()
gradient.startPoint = CGPoint(x: CGFloat(0), y: CGFloat(1)) gradient.endPoint = CGPoint(x: CGFloat(1), y: CGFloat(0)) gradient.frame = YOURVIEW.bounds gradient.colors = [UIColor.red.cgColor, UIColor.green.cgColor] gradient.colors = [ UIColor(red: 255.0/255.0, green: 56.0/255.0, blue: 224.0/255.0, alpha: 1.0).cgColor,UIColor(red: 86.0/255.0, green: 13.0/255.0, blue: 232.0/255.0, alpha: 1.0).cgColor,UIColor(red: 16.0/255.0, green: 173.0/255.0, blue: 245.0/255.0, alpha: 1.0).cgColor] gradient.locations = [0.0 ,0.6 ,1.0] YOURVIEW.layer.insertSublayer(gradient, at: 0)

- 1,654
- 14
- 17
-
1I used this approach, changing "topview" to the name of my IBoutlet for my view. I deleted the "SearchView" line. – jessi May 13 '17 at 04:04
-
Good plan - maybe also note that you can use either of the gradient.colors set ups. So, if you comment out the simple gradient.colors using named UI colors, the image is the same, but if you comment out the other one, the color gradient is then relying on the red to green. Users can do either one. – jessi May 13 '17 at 07:42
In Swift 3.1 I have added this extension to UIView
import Foundation
import UIKit
import CoreGraphics
extension UIView {
func gradientOfView(withColours: UIColor...) {
var cgColours = [CGColor]()
for colour in withColours {
cgColours.append(colour.cgColor)
}
let grad = CAGradientLayer()
grad.frame = self.bounds
grad.colors = cgColours
self.layer.insertSublayer(grad, at: 0)
}
}
which I then call with
class OverviewVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.gradientOfView(withColours: UIColor.red,UIColor.green, UIColor.blue)
}
}

- 650
- 4
- 15
I have implemented this in my code.
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 31.0f)];
view1.backgroundColor = [UIColor clearColor];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view1.bounds;
UIColor *topColor = [UIColor colorWithRed:132.0/255.0 green:222.0/255.0 blue:109.0/255.0 alpha:1.0];
UIColor *bottomColor = [UIColor colorWithRed:31.0/255.0 green:150.0/255.0 blue:99.0/255.0 alpha:1.0];
gradient.colors = [NSArray arrayWithObjects:(id)[topColor CGColor], (id)[bottomColor CGColor], nil];
[view1.layer insertSublayer:gradient atIndex:0];
Now I can see a gradient on my view.

- 791
- 1
- 5
- 5
To give gradient color to UIView (swift 4.2)
func makeGradientLayer(`for` object : UIView, startPoint : CGPoint, endPoint : CGPoint, gradientColors : [Any]) -> CAGradientLayer {
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = gradientColors
gradient.locations = [0.0 , 1.0]
gradient.startPoint = startPoint
gradient.endPoint = endPoint
gradient.frame = CGRect(x: 0, y: 0, w: object.frame.size.width, h: object.frame.size.height)
return gradient
}
How to use
let start : CGPoint = CGPoint(x: 0.0, y: 1.0)
let end : CGPoint = CGPoint(x: 1.0, y: 1.0)
let gradient: CAGradientLayer = makeGradientLayer(for: cell, startPoint: start, endPoint: end, gradientColors: [
UIColor(red:0.92, green:0.07, blue:0.4, alpha:1).cgColor,
UIColor(red:0.93, green:0.11, blue:0.14, alpha:1).cgColor
])
self.vwTemp.layer.insertSublayer(gradient, at: 0)

- 15,269
- 2
- 94
- 81
This framework is good for gradients and other UI modifications in Historyboard: Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.
With this you can select a view, set the class to AnimatableView, and from Interface Builder property set gradients and preview results in realtime.
See this to know how apply gradients to UIView.

- 563
- 5
- 16
For a barebones UIView
subclass in Swift:
class GradientView: UIView {
var startColor: UIColor?
var endColor: UIColor?
override func draw(_ rect: CGRect) {
// do not call super
if let startColor = startColor,
let endColor = endColor {
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: rect.width, height: rect.height)
gradient.colors = [startColor.cgColor, endColor.cgColor]
layer.addSublayer(gradient)
}
}
}
Usage with auto layout:
let g = GradientView()
g.startColor = .red
g.endColor = .green
g.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(g)
// add constraints

- 11,654
- 3
- 38
- 51
Swift
Function Code: source code
you can use this function to create gradient color in view.
self.gradientColor(yourView:View, startColor: UIColor.red, endColor: UIColor.white, colorAngle: 270)

- 1
- 3