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

Buttons are a staple of all apps, big and small.

In this tutorial, you’ll learn how to take your app’s buttons to the next level using the UIButton Configuration API introduced in iOS 15. This API provides a flexible way to declare the style of buttons and have that style change when the state changes.

More specifically, you’ll learn how to do the following with the UIButton Configuration API:

  • Style buttons with ease.
  • Add images and SF Symbols to buttons.
  • Show a spinner on a button.
  • Update a button’s configuration dynamically.

Read on to discover everything you need to know to start configuring buttons!

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

A quick refresher: In iOS 14, Apple introduced the UIAction API for UIButton, which removed the need for the target-action pattern. Here’s a brief example of how to use this API:

button.addAction(
  UIAction { _ in
    print("You tapped the button!")
  }
)

When tapping the button, the block will be called and the print statement will execute.

If you’ve used a completion handler-based API before, this new UIAction API should feel familiar.

Now you’ll learn how to use the Configuration API to take your button’s styles to the next level with ease.

Beginning Adoption of UIButton.Configuration

Build and run the starter project. Then tap on the person icon.

The sample app's sign-in page, with two buttons: Sign In, and Get Help. Both buttons have no styling other than the default blue tinted title.

This opens the SignInViewController view controller. As you can see, it looks quite bland. Fortunately, this is easy to fix with the new Configuration API!

At a high level, there are four primitive options for a button configuration. They come as four different functions on UIButton.Configuration that generate a configuration object based on that template. The four options are as follows:

  • .plain: A plain button with a transparent background.
  • .filled: A button whose background is filled with a color.
  • .gray: A button with a gray background.
  • .tinted: A button whose background is tinted with a color.

Styling Options for Buttons

To start styling buttons, open SignInViewController.swift, and find signInButton.

At the top, inside the initializer closure, add the following code

var config = UIButton.Configuration.filled()

This created a basic configuration object based on the filled template.

Once you have a configuration object, there are many options you can modify to create the perfect button!

For example, you can change the size of the button and the style of its corners. To do that, add the following code underneath the code you just added:

config.buttonSize = .large
config.cornerStyle = .medium

This sets the button size to large and the corner style to medium. You could have a play with the different options here later if you wish.

Another option on UIButton.Configuration is titleTextAttributesTransformer, which allows you to modify properties of the button’s title label.

Additionally, there’s a similar property, subtitleTextAttributesTransformer, for modifying the button’s subtitle’s properties.

You’ll now set up a titleTextAttributesTransformer to change the font of the “Sign In” button.

Add the following underneath the code you just added:

config.titleTextAttributesTransformer =
  UIConfigurationTextAttributesTransformer { incoming in
    // 1
    var outgoing = incoming
    // 2
    outgoing.font = UIFont.preferredFont(forTextStyle: .headline)
    // 3
    return outgoing
  }

Here’s what you’re doing inside the transformer block:

  1. Create a mutable reference to the incoming property named outgoing so you can modify the attributes.
  2. Set the font of the title on outgoing.
  3. After that, return outgoing to apply the changes.
Note: outgoing and incoming are AttributeContainer types, which reflect several properties of UILabel.

Now the button’s title will appear with the correct font once the configuration is applied.

Adding Images

Another great feature of the Configuration API is the ability to add images to your buttons.

You want to add a chevron icon to the end of the “Sign In” button.

Add the following code underneath the code you just added:

// 1
config.image = UIImage(systemName: "chevron.right")
// 2
config.imagePadding = 5
// 3
config.imagePlacement = .trailing
// 4
config.preferredSymbolConfigurationForImage
  = UIImage.SymbolConfiguration(scale: .medium)

This code does the following:

  1. Initializes a UIImage with the chevron.right SF Symbol.
  2. Adds five points of padding between the title and the image.
  3. Places the image at the trailing end of the button.
  4. Sets the SF Symbol’s scale to .medium.
Note: If you are unfamiliar with SF Symbols then you might want to check out our SF Symbols tutorial.

It’s almost time to test this new configuration on signInButton!

The last thing to do is tell the button about the new config object. At the end of the initializer, right before the return statement, add the following code:

button.configuration = config

Now, build and run.

The sign in-page, with the Sign In button styled to have a large blue background which stretches to the edges of the screen

Excellent! The button is looking beautiful with its new style :]

However… if you tap on the button, the new style makes the interaction feel a bit clunky:

An animated gif of the sign-in page, where the Sign In button is tapped and changes text to Signing In, then back to Sign In after a one-second delay.

To be clear: When you tap on the button, it’s hard to see that the sign-in request is processing. Wouldn’t it be great if the button style updated automatically when the sign-in is in progress?

Introducing the Configuration Update Handler

As it turns out, there is a way to update the button automatically when the state changes.

Introducing… configurationUpdateHandler!

configurationUpdateHandler is a closure called when the button’s configuration changes. You can use it to change the configuration based on your app’s state.

SignInViewController has a Boolean property named signingIn, which you’ll use inside configurationUpdateHandler to change the button’s style.

Add the following code right before you set button.configuration:

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

  // 2
  config?.showsActivityIndicator = self.signingIn
  // 3
  config?.imagePlacement = self.signingIn ? .leading : .trailing
  // 4
  config?.title = self.signingIn ? "Signing In..." : "Sign In"

  // 5
  button.isEnabled = !self.signingIn

  // 6
  button.configuration = config
}

Here’s what you’re doing in this code:

  1. First, grab a copy of the button’s configuration and store it in a variable so you can modify it.
  2. Display the activity indicator if the user is signing in.
  3. The activity indicator’s position relative to the title is based on imagePlacement, so if the user is signing in, ensure it appears on the .leading edge, and if they aren’t signing in, revert back to .trailing to properly show the chevron.
  4. Set the title to Signing In… when the user is signing in, and set it to Sign In when they aren’t.
  5. Disable the button if the user is signing in.
  6. Finally, update the button’s configuration so your changes are reflected.

As you saw, UIButton.Configuration has a property named showsActivityIndicator. When true, the button’s image (regardless of whether it has one or not) will be replaced with an activity indicator.

The indicator’s position and padding relative to the title is based on imagePlacement and imagePadding.

The last thing to do is inform the button that the configuration needs to be updated whenever signingIn changes.

Find the signingIn property and replace the contents of the didSet block with the following code:

signInButton.setNeedsUpdateConfiguration()

setNeedsUpdateConfiguration informs the system that the button’s configuration needs to change.

Build and run.

An animated gif of the sign-in page, where the Sign In button is tapped and changes text to Signing In, and the background becomes translucent with a spinning activity indicator to the right of to the title before reverting back its original style after a one-second delay.

Looking great!

Next, you can apply a similar style to another button.