I have been using png gradient background image for my buttons. But these images don’t scale well and the corners always look off. So today I changed them all to custom buttons using the QuartzCore framework.
The code below creates a blue gradient button with rounded corners that can be any size.
First, create a new objective-c class and make it a subclass of UIButton. Here is my .h file:
#import < uikit /UIKit.h >
#import < quartzcore /QuartzCore.h >
@interface CustomButton : UIButton
@end
And here is my .m code:
#import "CustomButton.h"
@interface CustomButton ()
@property (strong,nonatomic) CAGradientLayer *backgroundLayer, *highlightBackgroundLayer;
@property (strong,nonatomic) CALayer *innerGlow;
@end
@implementation CustomButton
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self)
{
[self drawButton];
[self drawInnerGlow];
[self drawBackgroundLayer];
[self drawHighlightBackgroundLayer];
_highlightBackgroundLayer.hidden = YES;
if (self.imageView)
[self bringSubviewToFront:self.imageView];
}
return self;
}
- (void)drawButton
{
CALayer *layer = self.layer;
layer.cornerRadius = 10.0f;
self.clipsToBounds = YES;
layer.borderWidth = 1;
layer.borderColor = [UIColor colorWithRed:48.0f/255.0f green:107.0f/255.0f blue:189.0f/255.0f alpha:1.0f].CGColor;
}
- (void)drawBackgroundLayer
{
NSArray *colors = (@[(id)[UIColor colorWithRed:129.0f/255.0f green:165.0f/255.0f blue:215.0f/255.0f alpha:1.0f].CGColor,
(id)[UIColor colorWithRed:48.0f/255.0f green:107.0f/255.0f blue:189.0f/255.0f alpha:1.0f].CGColor ]);
[self drawBackgroundLayerWithGradient:colors];
}
-(void)drawHighlightBackgroundLayer
{
NSArray *colors = (@[(id)[UIColor colorWithRed:90.0/255.0f green:137.0f/255.0f blue:203.0f/255.0f alpha:1.0f].CGColor,
(id)[UIColor colorWithRed:30.0/255.0f green:48.0f/255.0f blue:69.0f/255.0f alpha:1.0f].CGColor ]);
[self drawHighlightBackgroundLayerWithGradient:colors];
}
-(void)drawBackgroundLayerWithGradient:(NSArray*)colors
{
if (!_backgroundLayer)
{
_backgroundLayer = [CAGradientLayer layer];
_backgroundLayer.colors = colors;
_backgroundLayer.locations = (@[ @0.0f, @1.0f ]);
[self.layer insertSublayer:_backgroundLayer atIndex:0];
}
}
-(void)drawHighlightBackgroundLayerWithGradient:(NSArray*)colors
{
if (!_highlightBackgroundLayer)
{
_highlightBackgroundLayer = [CAGradientLayer layer];
_highlightBackgroundLayer.colors = colors;
_highlightBackgroundLayer.locations = (@[ @0.0f, @1.0f ]);
[self.layer insertSublayer:_highlightBackgroundLayer atIndex:0];
}
}
- (void)drawInnerGlow
{
if (!_innerGlow)
{
_innerGlow = [CALayer layer];
_innerGlow.cornerRadius= 10.0f;
_innerGlow.borderWidth = 1;
_innerGlow.borderColor = [[UIColor whiteColor] CGColor];
_innerGlow.opacity = 0.5;
[self.layer insertSublayer:_innerGlow atIndex:2];
}
}
- (void)layoutSubviews
{
// Set inner glow frame (1pt inset)
_innerGlow.frame = CGRectInset(self.bounds, 1, 1);
// Set gradient frame (fill the whole button))
_backgroundLayer.frame = self.bounds;
// Set inverted gradient frame
_highlightBackgroundLayer.frame = self.bounds;
[super layoutSubviews];
}
- (void)setHighlighted:(BOOL)highlighted
{
// Disable implicit animations
[CATransaction begin];
[CATransaction setDisableActions:YES];
// Hide/show inverted gradient
_highlightBackgroundLayer.hidden = !highlighted;
_backgroundLayer.hidden = highlighted;
[CATransaction commit];
[super setHighlighted:highlighted];
}
+ (CustomButton *)buttonWithType:(UIButtonType)type
{
return [super buttonWithType:UIButtonTypeCustom];
}
Then all you have to do is create a button in Interface Builder like you normally would, and change its class to CustomButton (third tab in the utilities panel). Voila! Pretty gradient buttons. Obviously, you can change all kinds of things in this code snippet to make the button look how you wish.