UISwitch
iOS development
Swift programming
UIKit customization
mobile app design

Change color of UISwitch in off state

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Changing the off-state appearance of UISwitch is less obvious than changing the on-state color. UIKit gives you onTintColor for the on track, but the off state often needs a combination of tintColor, backgroundColor, and rounded corners before the visual change looks correct.

Know Which Property Affects Which Part

UISwitch uses several color-related properties:

  • 'onTintColor controls the track when the switch is on'
  • 'thumbTintColor controls the circular thumb'
  • 'tintColor affects the border or edge of the off-state track'

The confusing part is that setting tintColor alone often does not make the off state look filled. The off track has transparency, so developers usually also set backgroundColor to the same color and round the switch background.

A Common Off-State Styling Pattern

This pattern is widely used in UIKit code:

swift
1import UIKit
2
3let toggle = UISwitch(frame: .zero)
4toggle.isOn = false
5
6toggle.onTintColor = .systemGreen
7toggle.tintColor = .systemGray4
8toggle.backgroundColor = .systemGray4
9toggle.thumbTintColor = .white
10
11toggle.layer.cornerRadius = toggle.frame.height / 2

The important line for the off state is backgroundColor. Without it, the switch may still look partly transparent instead of showing a solid off-state track.

Apply the Style After Layout Is Known

If the switch is created with Auto Layout or inside a storyboard, apply the style after the control has a reliable size. In many cases viewDidLoad() is enough for a standard UISwitch, but viewDidLayoutSubviews() is safer if the control size or transform changes.

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    @IBOutlet private weak var wifiSwitch: UISwitch!
5
6    override func viewDidLayoutSubviews() {
7        super.viewDidLayoutSubviews()
8        styleSwitch(wifiSwitch)
9    }
10
11    private func styleSwitch(_ control: UISwitch) {
12        control.onTintColor = .systemBlue
13        control.tintColor = .systemGray3
14        control.backgroundColor = .systemGray3
15        control.thumbTintColor = .white
16        control.layer.cornerRadius = control.frame.height / 2
17    }
18}

The corner radius matters because once you set the background color, the control can look like a small rectangle unless its background is rounded to match the switch shape.

Interface Builder and Reuse Considerations

If the switch comes from a storyboard or a table-view cell, remember that reused controls can keep styling from previous configuration code if you only set part of the appearance. Treat off-state styling as part of your full control setup rather than as a one-line tweak.

For repeated use across a screen or app, moving the style into a helper method or subclass keeps the result consistent. That is especially useful when designers later adjust the gray level, thumb color, or accessibility contrast requirements.

Keep the Control Recognizable

Minor customization is usually fine, but UISwitch is a standard platform control and users expect it to behave and look familiar. If the design pushes too far away from the default appearance, accessibility and usability can suffer.

A few practical checks:

  • test both on and off states against the screen background
  • make sure the thumb remains clearly visible
  • verify sufficient contrast for the off state

If the design language needs a drastically different toggle, a custom control can be a better choice than forcing UISwitch to imitate something it was not built to be.

Common Pitfalls

  • Setting only tintColor and expecting a fully colored off-state track.
  • Forgetting to set backgroundColor to match the intended off color.
  • Leaving the corner radius unchanged and ending up with a rectangular background.
  • Styling the switch too early in a layout path where the final size is not ready yet.
  • Over-customizing the control until it no longer feels like a native iOS switch.

Summary

  • 'onTintColor controls the on-state track, but the off state usually needs more than tintColor.'
  • For a visible off-state color, set both tintColor and backgroundColor.
  • Match the corner radius to half the control height so the background stays rounded.
  • Apply styling after layout if the switch size is not final at creation time.
  • If the design needs a radically different toggle, a custom control is often the cleaner solution.

Course illustration
Course illustration

All Rights Reserved.