Saturday, August 21, 2010

Designing beautiful gradient buttons in Cocoa with Core Graphics- Part 3

Hi All.
Last time we left off with a gradient-like view, but we created it with a static background color.
Now we are going to take a static color like this:

...and turn it into this with code.


Let's get started:
1. If we look at a gradient that we produce from a static color, we can work with different color schemes, the most beneficial IMO, is the Hue, Brightness, Saturation mode.
You can make a gradient just by changing the brightness value, but we found you get better results if you add a little bit of change to the Hue value.


2. For this to work, you will need a function that can take RGB values and translate them to HSB values,
I confess that I didn't write such a function myself, you can find one easily on the web.

3. We'll start by getting the CGColor of our base color and transform it to HSB values.


CGColorRef cgBaseColor = baseColor.CGColor;

We then get the HSB values:

float hsbValues[3];
CGColorRef cgBaseColor = baseColor.CGColor;
transformRGBtoHSB(CGColorGetComponents(cgBaseColor), hsbValues);
float hue=hsbValues[0];
float saturation=hsbValues[1];
float brightness=hsbValues[2];

You can do this by using two gradients, but we used three instead and placed the last one closer to the end point to get better results.
We also used a parameter called intensity to control the amount of gradient applied.

UIColor *middleColor = [UIColor colorWithHue:hue-(intensity*0.055*0.5
  saturation:saturation 
          brightness:brightness*(1.0-(intensity*0.8*0.5)) 
               alpha:1.0];
UIColor *endColor    = [UIColor colorWithHue:hue-(intensity*0.055)       saturation:saturation 
  brightness:brightness*(1.0-(intensity*0.8)) 
       alpha:1.0];

4. Let's start setting up the gradient:

To create a gradient we need a colorSpace, an array of colors, and an array of locators:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSArray *colorArray = [NSArray arrayWithObjects:(id)(baseColor.CGColor), (id)(middleColor.CGColor), (id)(endColor.CGColor), nil];
CGFloat locations[3];
locations[0] = 0.0;
locations[1] = 0.7;
locations[2] = 1.0;
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)colorArray, locations);
5. Now that our gradient is set, we can draw it:

CGPoint myStartPoint, myEndPoint;
myStartPoint.x = 0.0;
myStartPoint.y = 0.0;
myEndPoint.x = 0.0;
myEndPoint.y = 105.0;
CGContextDrawLinearGradient (context, gradient, myStartPoint, myEndPoint, kCGGradientDrawsAfterEndLocation);

6. Don't forget to release it :)

CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);

7. You're done! We'll just replace the UIRectFill method with the new one we created and voila! 
Here's a nice looking gradient:


And that's all there is to it, here's a screenshot of it in Deca Sudoku 2.0.

Hope you enjoyed this!
Uri.


No comments:

Post a Comment