Recently I needed custom UI control for iOS that had rounded corners and a gradient background. To make the user experience as rich as possible I wanted the background of the control to flatten when the user tapped it. There were plenty of examples of gradient buttons and rounded corner views but nothing did exactly what I needed.
After a bit of experimentation I found the easiest solution was to add a gradient layer to a custom UIControl and swap it with a different layer when the control became highlighted.
The first step was to was to create a custom UIControl class and add a gradient background layer:
#import <QuartzCore/QuartzCore.h> @interface GradientControl : UIControl { CAGradientLayer *normalBackground; } @end @implementation GradientControl - (id) initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { self.backgroundColor = [UIColor clearColor]; normalBackground = [CAGradientLayer layer]; normalBackground.frame = self.bounds; normalBackground.cornerRadius = 10; normalBackground.borderWidth = 1; normalBackground.borderColor = [[UIColor whiteColor] CGColor]; normalBackground.colors = [NSArray arrayWithObjects: (id)[[UIColor colorWithHexString:@"a9aeba"] CGColor], (id)[[UIColor colorWithHexString:@"7e8790"] CGColor], (id)[[UIColor colorWithHexString:@"6f778b"] CGColor], (id)[[UIColor colorWithHexString:@"5b657d"] CGColor], nil]; normalBackground.locations = [NSArray arrayWithObjects: [NSNumber numberWithFloat:0], [NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:0.51], [NSNumber numberWithFloat:1], nil]; } return self; } @end
Next we need to add a UIView to our main view in Interface Builder and set the class property to our new custom GradientControl:
Now if we run it in the simulator we can see our new shiny rounded gradient control:
Although this new component responds to events and triggers any actions that you assign it doesn’t give any visual feedback to taps. This can be solved by creating a second gradient layer and swapping the layers when the highlight value changes:
#import <QuartzCore/QuartzCore.h> @interface GradientControl : UIControl { CAGradientLayer *normalBackground; CAGradientLayer *highlightBackground; } @end @implementation GradientControl - (id) initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { self.backgroundColor = [UIColor clearColor]; normalBackground = [CAGradientLayer layer]; // setup normal background... highlightBackground = [CAGradientLayer layer]; // setup highlight background... } return self; } - (void) setHighlighted:(BOOL)aHighlighted { BOOL oldHighlighted = self.highlighted; [super setHighlighted:aHighlighted]; if (oldHighlighted == aHighlighted) { return; } if (aHighlighted) { [self.layer replaceSublayer:normalBackground with:highlightBackground]; } else { [self.layer replaceSublayer:highlightBackground with:normalBackground]; } } @end
Now when we tap the control the background seamlessly switches to the highlighted background:
The last thing to do is to add some setters to change the background colours and the border. With these we can easily create a range of gradient controls:
The full code with examples can be found on GitHub.



