UIButton Configuration Tutorial: Getting Started

Learn how to give your buttons some style and color using the UIButton Configuration API. By Jordan Osterberg.

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

Styling the Get Help Button

Find the helpButton property. At the top of the initialization closure add the following code:

var config = UIButton.Configuration.tinted()
config.buttonSize = .large
config.cornerStyle = .medium

Then once again set the configuration right before the return statement like so:

button.configuration = config

Build and run.

The sign-in page, with styling applied to the Sign In and Get Help buttons

Excellent! Now, you’ll learn about how to create toggle buttons.

Creating Toggle Buttons

A wonderful use case of configurationUpdateHandler is that of toggle buttons.

Using the update handler, you can change a button’s icon based on its current state.

Build and run the app. The first screen you see if the BookListViewController.

The list of books, where the trailing add to cart button displays the text 'Add'

Notice on each of the book cells, there’s a button for adding them to the cart, located on the trailing edge.

If you tap on one, the text changes from “Add” to “Remove”. While this isn’t a bad user experience, implementing the new button configuration API will make it much better.

First, open BookCollectionCell.swift.

Next, locate the addToCartButton property. At the top of its initializer closure add the following code:

var config = UIButton.Configuration.gray()

This sets up a new configuration object from the gray template this time.

Then, set a default image for the button using the cart.badge.plus SF Symbol:

config.image = UIImage(systemName: "cart.badge.plus")

As you’ve done a few times now, set the button’s configuration right before the return statement:

button.configuration = config

Great job! Now, build and run.

The book list, with the trailing add to cart button that now has an icon of a cart next to the Add text, along with a gray background

The icon appears correctly, however, the title feels unnecessary, and the icon doesn’t change when a book is added to the cart. You’ll fix this now.

Replace this line of code, which sets the button’s title:

button.setTitle("Add", for: .normal)

With configurationUpdateHandler:

button.configurationUpdateHandler = { [unowned self] button in
  // 1
  var config = button.configuration

  // 2
  let symbolName = self.isBookInCart ? "cart.badge.minus" : "cart.badge.plus"
  config?.image = UIImage(systemName: symbolName)

  // 3
  button.configuration = config
}

Here’s what happens in the code above:

  1. As you did earlier, grab a mutable copy of the button’s current configuration.
  2. Modify config‘s image property based on the isBookInCart of the BookCollectionCell class.
  3. Finally, update the button’s configuration.

Once again we need to tell the button to update its configuration at the right time. In this case it is when isBookInCart changes.

Find the isBookInCart property. Then change the contents of the didSet handler with the following code:

addToCartButton.setNeedsUpdateConfiguration()

Build and run.

The book list, with the trailing add to cart button only displaying the icon

It works perfectly! The image changes to reflect whether the book is in the user’s cart.

Now it’s time to check out!

Creating Pop-Up Buttons

Tap the cart button in the navigation bar and gaze upon the unstyled buttons.

The cart screen, with a bottom panel that is unsettled. There are two buttons: Shipping Speed and Checkout

Additionally, if you change the shipping speed, there’s no indication of the current shipping selection.

Oh, the horror! Fortunately, you have the tools to fix this up in a jiffy!

To get started, you’ll style the shipping speed button and configure it so the current shipping speed appears on the label.

Open CartPanelView.swift.

First, locate the shippingSpeedButton property. Next, at the top of the initializer closure add the following code:

var config = UIButton.Configuration.tinted()
config.buttonSize = .medium
config.cornerStyle = .medium
config.titleTextAttributesTransformer = 
  UIConfigurationTextAttributesTransformer { incoming in
    var outgoing = incoming
    outgoing.font = UIFont.preferredFont(forTextStyle: .headline)
    return outgoing
  }

This creates a tinted configuration and sets its size and corner style. Then creates a title text transformer to set the button’s font.

Once again add the following code right before the return statement:

button.configuration = config

Build and run, and you’ll see the new styling applied to the shipping speed button.

The cart screen, with the Shipping Speed button now styled with a tinted background

However, selecting a shipping speed still doesn’t change the button’s title. You fix this next.

Changing the Button’s Title

Changing the title is an extremely easy job using the new changesSelectionAsPrimaryAction on UIButton!

This button uses the menu property to set a menu that pops up when the button is tapped. The new changesSelectionAsPrimaryAction property allows you to tell UIKit that it should use the selection from the menu as the title of the button.

Add the following code right after button.showsMenuAsPrimaryAction = true:

button.changesSelectionAsPrimaryAction = true

Now, build and run, and change the shipping speed in the cart view:

The cart screen, where the Shipping Speed button now displays the current speed as the button's title. The user taps on it and switches between Express Shipping and Standard Shipping to show the change in button title

Awesome! There’s now an easy way to view and change the shipping speed of the order.

All that’s left is to make the checkout button styled, and then the app will be complete!

Styling the Checkout Button

Locate the checkoutButton property, and at the top of the initializer closure, create a basic configuration for it like you’ve done several times now:

var config = UIButton.Configuration.filled()
config.buttonSize = .large
config.cornerStyle = .medium
config.imagePlacement = .leading
config.imagePadding = 5
config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { incoming in
  var outgoing = incoming
  outgoing.font = UIFont.preferredFont(forTextStyle: .headline)
  return outgoing
}

You should be aware by now of what’s happening here!

When you’re done, the checkout button will display an activity indicator as the order is placed. The image properties you set above will control its placement and padding between the title.

And once again add the following code right before the return statement:

button.configuration = config

Almost done! Add a configurationUpdateHandler to update the button style when state changes:

button.configurationUpdateHandler = { [unowned self] button in
  // 1
  var config = button.configuration

  // 2
  config?.showsActivityIndicator = self.checkingOut
  // 3
  config?.title = self.checkingOut ? "Checking Out..." : "Checkout"

  // 4
  button.isEnabled = !self.checkingOut

  // 5
  button.configuration = config
}

Here’s what’s is happening:

  1. Store button‘s configuration in a mutable variable.
  2. Show the activity indicator when the user is checking out (based on the checkingOut property of the class).
  3. Change the title based on whether or not the user is checking out.
  4. Additionally, disable the button when checking out.
  5. Finally, save the changes to the configuration.

The last step is to make the usual call to setNeedsUpdateConfiguration when the state changes.

Find the checkingOut property. Replace the contents of the didSet block with the following code:

checkoutButton.setNeedsUpdateConfiguration()

Excellent! Build and run, and navigate to the cart.

The cart screen, with styles correctly and fully applied. The Checkout button has an activity indicator when tapped, which reverts after a second.

When you tap the checkout button, it displays the activity indicator for a second before reverting back to its previous state.

The app is complete, and you’re now a button enthusiast!