Core Graphics Tutorial: Glossy Buttons

In this Core Graphics tutorial, you’re going to tackle a different practical example – how to customize a UIButton. In the process, you’ll learn how to draw rounded rects, how to easily tint your Core Graphics drawings, and reinforce some of the concepts you’ve already covered.

But I think what’s been missing in this discussion is a detailed Core Graphics tutorial for how to customize the buttons yourself, from start to finish. It’s pretty simple, and this way you can get the exact look you’re going for in your app.

So let’s get started and make some buttons!

Getting Started

Start up Xcode and create a new project (File\New\Project…). Select the iOS\Application\Single View Application template and click Next.

Enter CoolButton for the Product Name, enter an Organization Name (anything will do), enter a Company Identifier prefix such as com.mycompany, select iPhone for Devices, and checkmark Use Storyboards and Use Automatic Reference Counting.

Next go to File\New\File…, choose the iOS\Cocoa Touch Class\Objective-C class template, and click Next. In the next menu, enter the name CoolButton as the class name. In the subclass field, type UIButton. Click Next then Create.

Here you are just initializing the variables and filling the whole thing with some pre-configured color to make sure everything’s working OK to start.

Note that you’re using a different constructor to make the color this time – rather than colorWithRed:green:blue, you use colorWithHue:saturation:brightness. This will make things a bit easier for you later on.

The last thing you do here is override the setters for the hue, saturation, and brightness properties so you call setNeedsDisplay when they are called. This will force your view to redraw when the user changes the color of the button.

Now switch over to ViewController.h and replace it with the following:

Here you’re declaring a reference to the button (which you’ll make in Interface Builder) and some callbacks for when the configuratoin slider values change (which you’ll also add in Interface Builder).

So go ahead and do that now. Open up MainStoryboard.storyboard, and drag a button, 3 labels, and 3 sliders onto the view. Also, deselect the Use Autolayout checkbox. It should look something like this:

Next, change the class of the UIButton to be a CoolButton by going to the Identity Inspector and changing the Class dropdown to CoolButton:

Also, make sure the Attributes Inspector is selected, and switch the drawing type of the Button to Custom to remove the default rounded corners of the button.

Then, control-drag from ViewController in the View Controller Scene panel on the left to the button and connect it to the coolButton outlet. Similarly, control-drag from each slider up to ViewController in the View Controller Scene panel on the left to connect it to the appropriate value changed callback.

Before leaving the storyboard, double click on the button to select the word “Button”, then press the delete key to delete the text.

One last thing before you try it out. First import the CoolButton class in ViewController.m. The top of the file should look like this:

Note that by default UISliders are set to go from 0.0 to 1.0 – which is perfect for your hue, saturation, and brightness values, which also range from 0.0 to 1.0, so you can just set them directly.

Build and run the project, and if all works well you should be able to play around with the sliders to fill the button with various colors:

Drawing Rounded Rectangles

It’s true that you can have square buttons, but these days it’s fashionable to have rounded rectangle buttons for the most part instead.

Note: Since the time of writing this article, flat rectangles are back in style, like in the Windows 8 user interface. Go figure! ;]

In the last Core Graphics tutorial, you learned how to draw arcs using the CGContextAddArc API. So you could definitely use that to draw an arc at each corner, and draw lines to connect them, based on stuff you already know.

But there’s an even easier way, where you don’t have to do quite so much math, and that actually fits in really well with drawing rounded rectangles. It’s the CGContextAddArcToPoint API.

The CGContextAddArcToPoint API lets you specify the arc to draw by specifying two tangent lines and a radius. The following diagram from the Quartz2D Programming Guide shows it pretty well:

So for the case of a rectangle, you obviously know the tangent lines for each arc you want to draw – they are just the edges of the rectangle! And you can specify the radius based on how rounded you want the rectangle to be – the larger, the more rounded.

The other neat thing about this function is if the current point in the path isn’t set to where you tell the arc to begin drawing, it will draw a line from the current point to the beginning of the path. So you can use this as a shortcut to draw a rounded rectangle in just a couple calls.

Since you’re going to create a bunch of rounded rects in this Core Graphics tutorial and in the future, add a helper function to Common.h/m to create a path for a rounded rect, given a rectangle.

If you don’t have it already, download Common.h/m where you left it off last time, and add it to your project.

Ok, so you define your two colors, then you use CGRectInset to get a slightly smaller rectangle (5 pixels on each side) where you’ll draw the rounded rect. You make it smaller so you have space to draw a shadow on the outside.

Next, you call the function you just wrote to create a path for your rounded rect. You then set the fill color and shadow, add the path to your context, and call CGContextFillPath to fill it with your current color.

Note you only want to run the code if your button isn’t currently highlighted (i.e. being tapped upon).

Build and run the app, and if all works well you should see the following:

Styling Your Button

Ok great, you have something that looks somewhat like a button now. But I bet you can do even better!

First thing you do is set up a bunch of colors that you’ll use later. There are a few generic colors, and then several colors based on the passed in parameters. Your base color is exactly how you’re set up, then you have several colors set up to be darker than the current color, to varying degress.

If you define your colors in this way, it makes it really easy to change the colors of your views, which can be quite handy for reusing code!

The next thing you do is clip to your rounded rect, and fill it with a gradient (rather than a single color). Build and run and your button is starting to look better:

Now add an inner path that has a slightly different gradient than the outer path, to create a bevel-type effect. Make the following mods to CoolButton.m:

You’re basically creating another rounded rect slightly smaller than the outerRect, and filling the area between the two rectangles with an alpha highlight gradient, using the Even-Odd Clip technique from last Core Graphics tutorial.

Build and run to check it out – it’s a very subtle touch so you might not notice it:

All you do here is stroke the outer path with black (2 points to avoid the 1px issues), and the inner path with a 1 point stroke.

“OMGBBQ”, you may say, “that is a 2 point stroke, not a 1 point stroke!” Well, you’re using a different technique to solve the 1px issue here – the “clipping mask” technique referred to earlier. Basically you set the stroke to be 2 points, and then clip off the outside region.

At the end, you release the paths you’ve created. If you had trouble following along, here is the complete method so far:

Build and run and now the button should look pretty good when you tap it!

Where To Go From Here?

Here is a sample project with all of the code you developed in the above Core Graphics tutorial.

Now that you’ve gone through all of the steps to create custom buttons from scratch, you should be intimately familiar with how to customize every aspect of the button to your liking for your project’s style!

Contributors

Ray is part of a great team - the raywenderlich.com team, a group of over 100 developers and editors from across the world. He...

Author

In this Core Graphics tutorial, you’re going to tackle a different practical example – how to customize a UIButton. In the process, you’ll learn how to draw rounded rects, how to easily tint your Core Graphics drawings, and reinforce some of the concepts you’ve already covered.