UIAppearance Tutorial: Getting Started
In this UIAppearance tutorial, you’ll learn how to make your app stand out by using Swift to customize the look and feel of standard UIKit controls. By Essan Parto.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
UIAppearance Tutorial: Getting Started
25 mins
- Getting Started
- Supporting Themes
- Applying Themes to Your Controls
- Applying Tint Colors
- Customizing the Navigation Bar
- Customizing the Navigation Bar Back Indicator
- Customizing the Tab Bar
- Customizing a Segmented Control
- Customizing Steppers, Sliders, and Switches
- Customizing a Single Instance
- Where to Go From Here?
Customizing a Segmented Control
One element that hasn’t changed yet is the segmented control that shows the currently selected theme. Time to bring that control into the wonderful world of theming.
Add the following code to the bottom of applyTheme()
in Theme.swift:
let controlBackground = UIImage(named: "controlBackground")?
.imageWithRenderingMode(.AlwaysTemplate)
.resizableImageWithCapInsets(UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3))
let controlSelectedBackground = UIImage(named: "controlSelectedBackground")?
.imageWithRenderingMode(.AlwaysTemplate)
.resizableImageWithCapInsets(UIEdgeInsets(top: 3, left: 3, bottom: 3, right: 3))
UISegmentedControl.appearance().setBackgroundImage(controlBackground, forState: .Normal,
barMetrics: .Default)
UISegmentedControl.appearance().setBackgroundImage(controlSelectedBackground, forState: .Selected,
barMetrics: .Default)
To understand the code above, first take a look at the controlBackground image in your asset catalog. The image may be tiny, but iOS knows exactly how to use it to draw the borders of your UISegmentedControl
, as it’s been pre-sliced and is resizable.
What does sliced mean? Take a look at the following magnified model:
There are four 3×3 squares, one in each corner. These squares are left untouched when resizing the image, but the gray pixels get stretched horizontally and vertically as required.
In your image, all the pixels are black and assume the tint color of the control. You instruct iOS how to stretch the image using UIEdgeInsets()
and passed 3
for the top, left, bottom and right parameters since your corners are 3×3.
Build and run. Tap the Gear icon in the top left and you’ll see that the UISegmentedControl
now reflects your new styling:
The rounded corners are gone and have been replaced by your 3×3 square corners.
Now that you’ve tinted and styled your segmented control, all that’s left is to tint the remaining controls.
Close the settings screen in the app, and tap the magnifier in the top right corner; you’ll see another segmented control which also has your customizations, along with a UIStepper
, UISlider
, and UISwitch
that still need to be themed.
Grab your brush and drop cloths — you’re going painting! :]
Customizing Steppers, Sliders, and Switches
To change the colors of the stepper, add the following lines to applyTheme()
in Theme.swift:
UIStepper.appearance().setBackgroundImage(controlBackground, forState: .Normal)
UIStepper.appearance().setBackgroundImage(controlBackground, forState: .Disabled)
UIStepper.appearance().setBackgroundImage(controlBackground, forState: .Highlighted)
UIStepper.appearance().setDecrementImage(UIImage(named: "fewerPaws"), forState: .Normal)
UIStepper.appearance().setIncrementImage(UIImage(named: "morePaws"), forState: .Normal)
You’ve used the same resizable image as you did for UISegmentedControl
; the only difference here is that UIStepper
segments become disabled when they reach their minimum or maximum values, so you needed to specify an image for this case as well. To keep things simple, you re-use the same image.
This not only changes the color of the stepper, but you also get some nice image buttons instead of the boring + and – symbols.
Build and run. Open Search to see how the stepper has changed:
UISlider
and UISwitch
need some theme lovin’ too.
Add the following code to applyTheme()
:
UISlider.appearance().setThumbImage(UIImage(named: "sliderThumb"), forState: .Normal)
UISlider.appearance().setMaximumTrackImage(UIImage(named: "maximumTrack")?
.resizableImageWithCapInsets(UIEdgeInsets(top: 0, left: 0.0, bottom: 0, right: 6.0)),
forState: .Normal)
UISlider.appearance().setMinimumTrackImage(UIImage(named: "minimumTrack")?
.imageWithRenderingMode(.AlwaysTemplate)
.resizableImageWithCapInsets(UIEdgeInsets(top: 0, left: 6.0, bottom: 0, right: 0)),
forState: .Normal)
UISwitch.appearance().onTintColor = theme.mainColor.colorWithAlphaComponent(0.3)
UISwitch.appearance().thumbTintColor = theme.mainColor
UISlider
has three main customization points: the slider’s thumb, the minimum track and the maximum track.
The thumb uses an image from your assets catalog, while the maximum track uses a resizable image in original rendering mode so it stays black regardless of the theme. The minimum track also uses a resizable image, but you’ve used the template rendering mode so that it inherits the tint of the template.
You’ve modified UISwitch
by setting thumbTintColor
to the main color and onTintColor
as a slightly lighter version of the main color t bump up the contrast between the two.
Build and run. Tap Search and your slider and switch should appear as follows:
As you saw with UISegmentedControl
, the appearance proxy customizes all instances of a class. But sometimes you don’t want a global appearance for a control — in these cases, you can customize just a single instance of a control.
Customizing a Single Instance
Open SearchTableViewController.swift and add the following lines to viewDidLoad()
:
speciesSelector.setImage(UIImage(named: "dog"), forSegmentAtIndex: 0)
speciesSelector.setImage(UIImage(named: "cat"), forSegmentAtIndex: 1)
Here you’re simply setting the image for each segment in the species selector.
Build and run. Open Search and you’ll see the segmented species selector looks like this:
iOS inverted the colors on the selected segment’s image without any work on your part; this is because images are automatically rendered in Template mode.
What about selectively changing the typeface on your controls? That’s easy as well.
Open PetTableViewController.swift and add the following two lines to the bottom of viewWillAppear()
:
view.backgroundColor = ThemeManager.currentTheme().backgroundColor
tableView.separatorColor = ThemeManager.currentTheme().secondaryColor
Next, add the following line to the end of tableView(_:cellForRowAtIndexPath:)
just before you return from the method:
cell.textLabel!.font = UIFont(name: "Zapfino", size: 14.0)
This simply changes font on the label that represents the pet’s name.
Build and run. Compare the before and after:
The image below shows the before and after results of the Search screen; I think you’ll agree that the new version is much less vanilla and much more interesting that the original:
Where to Go From Here?
You can download the finished project with all the tweaks from this tutorial here.
In addition to the tweaks you’ve already made, in Objective-C you can specify certain customizations to be applied to controls only when they’re contained in other controls of a specific class. For example, you can apply customizations to UITextField
, but only when contained in a UINavigationBar
.
Unfortunately, you cannot use this kind of customization in Swift, yet. The good news is that iOS 9 will add this functionality, and I’ll update this tutorial accordingly once it’s released.
I hope you enjoyed this UIAppearance tutorial and learned how easy it can be to tweak your UI. If you have any comments or questions about this tutorial, please join the forum discussion below!