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.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

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:

slicing

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:

segmented

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:

stepper

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:

slider-switch

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:

species

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:

theme_applied5-580x500

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:

theme_applied6-580x500

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!

Essan Parto

Contributors

Essan Parto

Author

Over 300 content creators. Join our team.