Making a simple toggle button with UIButton

It’s actually pretty straightforward to turn a UIButton into a toggle button. (checkbox, switch, whatever you prefer to call it!)

We can make use of the isSelected property that UIButton inherits from UIControl. All we need to do is connect a ‘Touch Up Inside’ action to the UIButton, that toggles this property:

@IBAction func toggleButton(_ sender: UIButton) {
  sender.isSelected.toggle()
}

Pretty easy right? Just like that, our button now toggles between the ‘Default’ and ‘Selected’ Control States. We can customize how these states look in the attributes inspector for the button.

Here I have customized a button to display either a tick or cross, depending on whether it’s selected, using SFSymbols ‘checkmark.circle’ and ‘xmark.circle’:

This seems to work pretty well, except for one minor detail. When the user has their finger down on the button, the button defaults to the ‘Default’ state (although darker). This works ok for the ‘unselected’ state, but doesn’t look quite right for the ‘selected’ state:

No Highlighted state selected.

How can we modify this state? If you open the ‘State Config’ combo box, you’ll find another state called ‘Highlighted’:

In UIButton this state refers to the state the button is in while the user’s finger is on it. Great! So we can modify the Image for this state too in the Attributes Inspector. Here I’m setting the image for the ‘Highlighted’ state to ‘xmark.circle.fill’:

Testing this out on the app, we see that this didn’t actually help us much! Sure, our ‘Default’ state has a neat ‘Highlighted’ state now, but our ‘Selected’ state still is defaulting to the ‘Default’ state when the user holds their finger down on the button:

What we need is to define the state for both ‘Selected’ AND ‘Highlighted’. Unfortunately that isn’t possible in the storyboard, but fortunately for us, we can do it in code. Just set up an @IBOutlet for your button, and then set the button’s image for this state in the viewDidLoad method. Here I am setting the image to ‘checkmark.circle.fill’ if the button is selected and the user holds their finger down on the button:

@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
  super.viewDidLoad()
  button.setImage(UIImage(systemName: "checkmark.circle.fill"), 
                  for: [.highlighted, .selected])
}

Finally! If we test the app now the button’s states should now be much more intuitive:

TL;DR

So — here again are the steps to creating a simple toggle button:

  1. Customize the button(for example, its image) in the attributes inspector of the storyboard for three states — ‘Default’ (off), ‘Highlighted’ (over) and ‘Selected’ (on).
  2. Connect the button to an IBOutlet so that you can set up a fourth state (a combination of ‘Highlighted’ and ‘Selected’) in the viewDidLoad method:
button.setImage(UIImage(systemName: "checkmark.circle.fill"), 
                  for: [.highlighted, .selected])

3. Connect the button to an IBAction that actually performs the toggling:

@IBAction func toggleButton(_ sender: UIButton) {
  sender.isSelected.toggle()
}

That’s it! Your button should work.

A reusable toggle button subclass

Of course, if you prefer you could set up a subclass of UIButton that handles the toggle operation for you:

import UIKit
class ToggleButton: UIButton {
  @IBInspectable var highlightedSelectedImage:UIImage?
  override func awakeFromNib() {
    self.addTarget(self, action: #selector(btnClicked(_:)), 
                   for: .touchUpInside)
    self.setImage(highlightedSelectedImage, 
                  for: [.highlighted, .selected])
  }
  @objc func btnClicked (_ sender:UIButton) {
    isSelected.toggle()
  }
}

This subclass contains an inspectable property highlightedSelectedImage that you can use to specify the image to display in the elusive fourth state (‘Selected’ and ‘Highlighted’) that is otherwise not available in the attributes inspector.

Connecting your button to this subclass in the identity inspector, you can now completely set up your toggle button in the storyboard. Hooray!👍

 

iOS development with Swift - book: https://manning.com/books/ios-development-with-swift video course: https://www.manning.com/livevideo/ios-development-with-swift-lv

Tagged with: ,
Posted in Swift

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: