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 itunes.apple.com/gb/app/gradient-creator/id1031070259?mt=12burrGGG– burrGGG2015-09-01 18:54:24 +00:00Commented Sep 1, 2015 at 18:54
-
Creating Gradient Colors Using CAGradientLayer appcoda.com/cagradientlayerMax– Max2019-04-18 07:52:12 +00:00Commented Apr 18, 2019 at 7: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.
10 Comments
view to self.view and it worked like a charm :)gradient.frame = view.bounds in viewDidAppear() and in didRotateFromInterfaceOrientation() or else the gradient wouldn't be sized properly.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
NSConstraintas usual on theUIView - Don't need to create sublayers (less memory use)
7 Comments
layerClass is no longer a function, it's a property so you have to override it like a property: stackoverflow.com/questions/28786597/…. Also you have to implement override init(frame: CGRect), check this answer: stackoverflow.com/questions/27374330/…. Thanks!init(frame:CGRect) though. I tested the updated code and it works fine.@IBDesignable is used?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 .
Comments
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];
4 Comments
viewDidLoadviewDidLoad, 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.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])
Comments
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
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)
}
}
1 Comment
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)
Comments
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)
1 Comment
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)
}
Comments
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]
}
}
Comments
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.
Comments
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]
Comments
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);
Comments
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)
2 Comments
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)
}
}
Comments
Swift
you can use this methods to create gradient color in view.
Use:
gradientColor(yourView:View, startColor: UIColor.gray, endColor: UIColor.red, colorAngle: 270)
Methods:
func gradientColor(yourView:UIView, startColor: UIColor, endColor: UIColor, colorAngle: CGFloat){
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
gradientLayer.locations = [0.0, 1.0]
let (start, end) = gradientPointsForAngle(colorAngle)
gradientLayer.startPoint = start
gradientLayer.endPoint = end
gradientLayer.frame = yourView.bounds
yourView.layer.insertSublayer(gradientLayer, at: 0)
yourView.layer.masksToBounds = true
}
func gradientPointsForAngle(_ angle: CGFloat) -> (CGPoint, CGPoint) {
let end = pointForAngle(angle)
let start = oppositePoint(end)
let p0 = transformToGradientSpace(start)
let p1 = transformToGradientSpace(end)
return (p0, p1)
}
func pointForAngle(_ angle: CGFloat) -> CGPoint {
let radians = angle * .pi / 180.0
var x = cos(radians)
var y = sin(radians)
if (abs(x) > abs(y)) {
x = x > 0 ? 1 : -1
y = x * tan(radians)
} else {
y = y > 0 ? 1 : -1
x = y / tan(radians)
}
return CGPoint(x: x, y: y)
}
func oppositePoint(_ point: CGPoint) -> CGPoint {
return CGPoint(x: -point.x, y: -point.y)
}
private func transformToGradientSpace(_ point: CGPoint) -> CGPoint {
return CGPoint(x: (point.x + 1) * 0.5, y: 1.0 - (point.y + 1) * 0.5)
}
1 Comment
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.
Comments
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)
Comments
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.
Comments
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



