11

If I have two UIColors, what's the best way to draw an even gradient between them over an arbitrarily-sized area?

I am guessing you would create a UIView subclass and use the CG drawing methods in the drawRect method. I just don't know which ones, or if there are any pitfalls to watch out for, like performance. Has anyone done this?

Mike McMaster
  • 7,573
  • 8
  • 37
  • 42
  • See this answer: http://stackoverflow.com/questions/422066/gradients-on-uiview-and-uilabels-on-iphone/1931498#1931498 – Bill Aug 18 '11 at 21:15

7 Answers7

50
#import <QuartzCore/QuartzCore.h>    
- (void) setGradient {
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = self.view.bounds;
    gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], (id)[[UIColor blackColor] CGColor], nil];
    [self.view.layer insertSublayer:gradient atIndex:0];     
}

Don't forget to add QuartzCore library to your project.

Anton Chikin
  • 1,746
  • 2
  • 17
  • 22
20

You'll want to use CGGradient. See the iPhone Dev Center "CGGradient Reference" document.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Ben Gottlieb
  • 85,404
  • 22
  • 176
  • 172
  • 1
    This link works better: http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/Introduction/Introduction.html – Mat Ryer Feb 10 '11 at 12:52
  • 2
    You could provide examples when leaving answer. – Mark Aug 11 '14 at 17:46
  • 1
    Link-only answers should always provide the critical information in the answer in case the link goes dead. – Sascha Wolf Dec 03 '15 at 09:57
3

The Swift way to add Gradient is :

    var view : UIView = UIView(frame: CGRectMake(0, 0, 320, 100))
    var g : CAGradientLayer = CAGradientLayer()
    g.frame = gradientView.bounds
    g.colors = ["000000".UIColor.CGColor , "111111".UIColor.CGColor]
    view.layer.insertSublayer(g, atIndex: 0)

UIColor() is a helper class for Swift to convert hex color to rgb color, highly recommended.

Reza_Rg
  • 3,345
  • 7
  • 32
  • 48
  • What's `"000000".UIColor.CGColor`? – JSmyth Mar 28 '16 at 21:26
  • @JSmyth It's a Swift's String extension that convert 6 digit String to UIColor. You can easily find it on github. – Reza_Rg Apr 03 '16 at 14:06
  • @reza-rg I mean I prompted you to mention this in your answer. Not everyone is using that extension in the end. I suggest you add at least a link to the extension. More than that, the answer is fine but it's really easy to go with a standard way of instantiating colors for the sake of simplicity (e.g. `UIColor.whiteColor().CGColor`) as the question is about gradients, not hex-representation of colors. Finally, `UIColor()` is not a helper class, it's a built-in object. – JSmyth Apr 04 '16 at 09:48
0

I found that using CAGradientLayer produced a gradient with noticeable stepping Ended up using this

http://evilrockhopper.com/tag/cggradient/

As per this question Gradients on UIView and UILabels On iPhone

Community
  • 1
  • 1
Luke
  • 3,375
  • 2
  • 22
  • 22
0

For views that draw text, such as UILabel, UITextView, and UITextField, you should add the gradient inside the drawRect function. (see this post for an example).

There are some great subclasses of UILabel, UITextView, and UITextField that allow you to add a gradient pretty easily (see JBGradient on GitHub).

Community
  • 1
  • 1
Jbryson
  • 2,875
  • 1
  • 31
  • 53
0

Same-ish solution as @Anton Chikin but a little more robust. Notice the override of layerClass... this way, you don't have to worry about setting the frame and the frame is automatically updated upon rotation & resize.

class GradientView: UIView {

    var colorA : UIColor = UIColor.greenColor() {
        didSet { updateGradient() }
    }
    var colorB : UIColor = UIColor.blueColor() {
        didSet { updateGradient() }
    }

    override class func layerClass() -> AnyClass {
        return CAGradientLayer.self
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        updateGradient()
    }

    func updateGradient() {
        if let gLayer = layer as? CAGradientLayer {
            gLayer.colors = [colorA.CGColor, colorB.CGColor]
        }
    }

}

If you're using IB, you can set the properties via "User Defined Runtime Attributes".

If you're not using IB, use the other initializer.

tybro0103
  • 48,327
  • 33
  • 144
  • 170
0

You can use the following to apply a gradient on the view

-(void)applyGradientEffecttoView:(UIView *)aView
 {
     // Create the colors

     UIColor *darkOp = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0];
     UIColor *lightOp =[UIColor colorWithRed:255.0f green:255.0f blue:255.0f alpha:0.0];

      // Create the gradient
      CAGradientLayer *gradient = [CAGradientLayer layer];

      // Set colors
      gradient.colors = [NSArray arrayWithObjects:
                        (id)lightOp.CGColor,
                        (id)darkOp.CGColor,
                        nil];
     gradient.locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.5],
                          nil];

    // Set bounds
     gradient.frame = aView.bounds;
 
   // Add the gradient to the view

  [aView.layer insertSublayer:gradient atIndex:0];
}
Dharman
  • 30,962
  • 25
  • 85
  • 135