Showing posts with label Buttons. Show all posts
Showing posts with label Buttons. Show all posts

Friday, June 25, 2010

Programmatic Gradient Buttons

type='html'>Thanks to a little insomnia, I decided to play around a little more with doing a programmatic gradient button. I started to create another gradient button, realized that the code was going to be 90% the same between the two style gradient buttons, so did a little refactoring. The result is a class you can subclass to easily make new gradient buttons. All you have to do is override three methods to specify the gradient to use when the button is in its normal state, the gradient to use when the button is in highlighted (pressed) state, and the corner radius. Here's what the alert-style button looks like now:

BlueGradientButton.h
#import <UIKit/UIKit.h>
#import "AbstractGradientButton.h"

@interface BlueGradientButton : AbstractGradientButton
{
}


@end


BlueGradientButton.m
#import "BlueGradientButton.h"

@implementation BlueGradientButton
- (CGGradientRef)createNormalGradient
{
CGFloat locations[3];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:3];
UIColor *color = [UIColor colorWithRed:0.283 green:0.32 blue:0.414 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[0] = 0.0;
color = [UIColor colorWithRed:0.82 green:0.834 blue:0.87 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[1] = 1.0;
color = [UIColor colorWithRed:0.186 green:0.223 blue:0.326 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[2] = 0.483;

CGGradientRef ret = CGGradientCreateWithColors(space, (CFArrayRef)colors, locations);
CGColorSpaceRelease(space);
return ret;
}

- (CGGradientRef)createHighlightGradient
{
CGFloat locations[4];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:4];
UIColor *color = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[0] = 0.0;
color = [UIColor colorWithRed:0.656 green:0.683 blue:0.713 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[1] = 1.0;
color = [UIColor colorWithRed:0.137 green:0.155 blue:0.208 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[2] = 0.51;
color = [UIColor colorWithRed:0.237 green:0.257 blue:0.305 alpha:1.0];
[colors addObject:(id)[color CGColor]];
locations[3] = 0.654;

CGGradientRef ret = CGGradientCreateWithColors(space, (CFArrayRef)colors, locations);
CGColorSpaceRelease(space);
return ret;
}

- (CGFloat)cornerRadius
{
return 7.0;
}

@end



Adding new gradient buttons is relatively simple, since all the heavy drawing is handled in the superclass based on the values you return in these three methods. You can check out the sample project that has two gradient buttons: one that simulates the alert style button and which also works for regular bar buttons, and one that simulates the red delete button. I'll likely add more styles later.

One important notice - the CFGradientRef returned by the two methods should not be released, the super class will release it when it's done. This is a bit of an oddity, but there is no CFGradientAutorelease() function, only a CFGradientRelease() function. I changed the name to start with "create". In the Core Foundation memory management rules, functions that use create return an object with retain count of 1. There probably is a more elegant way to deal with this situation, but none occurred to me and I didn't want to have to mess around with a callback to release the memory given how straightforward the usage is here.

You can download the project here. I've also added the project to Google Code if anyone wants to contribute additional elements.

Thursday, June 24, 2010

Improved Gradient Buttons

type='html'>I've been playing around a bit, improving my imageless gradient button class. The new version allows you to specify the gradient for the normal and highlighted state by populating two arrays, one with the colors that make up the gradients and another with the relative location for each color. I've gotten rid of the abstract parent class and individual child classes and all the functionality is now contained in a single class.

Screen shot 2010-05-19 at 11.48.50 PM.png
There are five built-in styles which can be seen in the image above, or you can manually set the gradient to any value you'd like. You can download the source codes from the Google code page. There are no restrictions or limitations on its use.

The easiest way to use these is to add a UIButton instance to your view in Interface Builder, then change the underlying class from UIButton to GradientButton. Because there's no way to create IB palettes for iPhone classes, you'll also have to implement viewDidLoad and set the gradient or use the existing methods there.

Wednesday, June 23, 2010

Gradient Buttons Yet Again

type='html'>I added two more button styles to the iPhone Gradient Buttons project and made stroke color and stroke weight configurable options. The two new styles look exactly like the old Black and White style, only the highlight state is a blue gradient. These simulate the style used in alert sheets in several Apple applications.

Screen shot 2010-05-21 at 4.29.17 PM.png

Some of the Core Graphics code was machine-generated and is in kind of rough shape, but it works. I'm thinking about refactoring the different styles methods into something shorter, perhaps a plist, or just C arrays with the different numeric values.

For some strange reason, when I try to use arrayWithObjects: instead of creating a mutable array and manually adding the colors one at a time, I get a NULL gradient back. I have no idea why, but it's working this way at least.

Anyone who wants to contribute, let me know, I'd be happy to add committers.