Programmatically create a UIView with color gradient

IosUiviewUicolor

Ios Problem Overview


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?

Ios Solutions


Solution 1 - Ios

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.

Solution 2 - Ios

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:

enter image description here

This is better in the following ways:

  • No need to set frame of CLayer
  • Use NSConstraint as usual on the UIView
  • Don't need to create sublayers (less memory use)

Solution 3 - Ios

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];

enter image description here

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)

enter image description here

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)

enter image description here

For more details description refer CAGradientLayer Doc

Hope this is help for some one .

Solution 4 - Ios

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];

Solution 5 - Ios

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

Solution 6 - Ios

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

Solution 7 - Ios

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

Solution 8 - Ios

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)

Solution 9 - Ios

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)

Solution 10 - Ios

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

Solution 11 - Ios

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.

Solution 12 - Ios

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

Solution 13 - Ios

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]

Solution 14 - Ios

Its a good idea to call the solutions above to update layer on the

viewDidLayoutSubviews 

to get the views updated correctly

Solution 15 - Ios

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

Solution 16 - Ios

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

Solution 17 - Ios

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

Solution 18 - Ios

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.

Solution 19 - Ios

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)

Solution 20 - Ios

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAllan JiangView Question on Stackoverflow
Solution 1 - IosArslan AliView Answer on Stackoverflow
Solution 2 - IosYuchenView Answer on Stackoverflow
Solution 3 - IosJaywant KhedkarView Answer on Stackoverflow
Solution 4 - IosSam FischerView Answer on Stackoverflow
Solution 5 - IosElijahView Answer on Stackoverflow
Solution 6 - IosblauzahnView Answer on Stackoverflow
Solution 7 - IosflocbitView Answer on Stackoverflow
Solution 8 - IosSiva VisakanView Answer on Stackoverflow
Solution 9 - IospatrickSView Answer on Stackoverflow
Solution 10 - IosTommie C.View Answer on Stackoverflow
Solution 11 - IosKendall Helmstetter GelnerView Answer on Stackoverflow
Solution 12 - IosAlexander VolkovView Answer on Stackoverflow
Solution 13 - IosGregPView Answer on Stackoverflow
Solution 14 - IosRonaldo AlbertiniView Answer on Stackoverflow
Solution 15 - IosTimur BernikovichView Answer on Stackoverflow
Solution 16 - IosAzharhussain ShaikhView Answer on Stackoverflow
Solution 17 - IosiCyberPaulView Answer on Stackoverflow
Solution 18 - IosPadmajaView Answer on Stackoverflow
Solution 19 - IosHardik ThakkarView Answer on Stackoverflow
Solution 20 - IosWo_0NDeRView Answer on Stackoverflow