Chapter 6
Working with SwiftUI Buttons and Gradient

Buttons initiate app-specific actions, have customizable backgrounds, and can include a title or an icon. The system provides a number of predefined button styles for most use cases. You can also design fully custom buttons.

- Apple's documentation (https://developer.apple.com/design/human-interface-guidelines/ios/controls/buttons/)

I don't think I need to explain what a button is. It's a very basic UI control that you can find in all apps and has the ability to handle users' touch, and trigger a certain action. If you have learned iOS programming before, Button in SwiftUI is very similar to UIButton in UIKit. It's just more flexible and customizable. You will understand what I mean in a while. In this chapter, I will go through with you this SwiftUI control and you're to learn the following techniques:

  1. How to create a simple button and handle the user's selection
  2. How to customize the button's background, padding and font
  3. How to add borders to a button
  4. How to create a button with both image and text
  5. How to create a button with a gradient background and shadows
  6. How to create a full-width button
  7. How to create a reusable button style
  8. How to add a tap animation

Creating a New Project with SwiftUI enabled

Okay, let's start with the basics and create a simple button using SwiftUI. First, fire up Xcode and create a new project using the Single View Application template. Type the name of the project. I set it to SwiftUIButton but you're free to use any other name. All you need to ensure is check the Use SwiftUI option.

Figure 1. Creating a new project
Figure 1. Creating a new project

Once you save the project, Xcode should load the ContentView.swift file and display a preview in the design canvas. In case the preview is not displayed, you can click the Resume button in the canvas.

Figure 2. Previewing the default content view
Figure 2. Previewing the default content view

It's very easy to create a button using SwiftUI. Basically, you can use the code snippet below to create a button:

Button(action: {
    // What to perform
}) {
    // How the button looks like
}

When creating a button, you need to provide two code blocks:

  1. What to perform - the code to perform after the button is tapped or selected by the user.
  2. How the button looks like - the code block that describes the look & feel of the button.

For example, if you just want to turn the Hello World label into a button, you can update the code like this:

struct ContentView: View {
    var body: some View {
        Button(action: {
            print("Hello World tapped!")
        }) {
            Text("Hello World")
        }
    }
}

Now the Hello World text becomes a tappable button as you can see it in the canvas.

Figure 3. Creating a simple button
Figure 3. Creating a simple button

The button is now non-tappable in the design canvas. To test it, click the Play button to run the app. However, in order to view the Hello World tapped message, you have to right-click the Play button and then choose Debug Preview. You will see the message on the console when you tap the button.

Figure 4. The console message can only be displayed in debug mode
Figure 4. The console message can only be displayed in debug mode

Customizing the Button's Font and Background

Now that you should know how to create a simple button, let's see how to customize its look & feel with the built-in modifiers. Say, to change the background and text color, you can use the background and foregroundColor modifiers like this:

Text("Hello World")
    .background(Color.purple)
    .foregroundColor(.white)

If you want to change the font type, you further use the font modifier and specify the font type (e.g. .title) like this:

Text("Hello World")
    .background(Color.purple)
    .foregroundColor(.white)
    .font(.title)

After the change, your button should look like the figure below.

Figure 5. Customizing the background and foreground color of a button
Figure 5. Customizing the background and foreground color of a button

As you can see, the button doesn't look very good. Wouldn't it be great to add some space around the text? To do that, you can use the padding modifier like this:

Text("Hello World")
    .padding()
    .background(Color.purple)
    .foregroundColor(.white)
    .font(.title)

After you made the change, the canvas should update the button accordingly. The button should now look much better.

Figure 6. Adding padding to the button
Figure 6. Adding padding to the button

The Order of Modifiers is Important

One thing I want to highlight is that the padding modifier should be placed before the background modifier. If you write the code like below, the end result will be different.

Figure 7. Placing the padding modifier after the background modifier
Figure 7. Placing the padding modifier after the background modifier

If you place the padding modifier after the background modifier, you can still add some paddings to the button but without the preferred background color. If you wonder why, you can read the modifiers like this:

Text("Hello World")
    .background(Color.purple) // 1. Change the background color to purple
    .foregroundColor(.white)  // 2. Set the foreground/font color to white
    .font(.title)             // 3. Change the font type
    .padding()                // 4. Add the paddings with the primary color (i.e. white)

Conversely, the modifiers will work like this if the padding modifier is placed before the background modifier:

Text("Hello World")
    .padding()                // 1. Add the paddings
    .background(Color.purple) // 2. Change the background color to purple including the padding
    .foregroundColor(.white)  // 3. Set the foreground/font color to white
    .font(.title)             // 4. Change the font type

Adding Borders to the Button

It doesn't mean the padding modifier should always place at the very beginning. It just depends on your button design. Let's say, you want to create a button with borders like this:

Figure 8. A button with borders
Figure 8. A button with borders

You can change the code of the Text control like below:

Text("Hello World")
    .foregroundColor(.purple)
    .font(.title)
    .padding()
    .border(Color.purple, width: 5)

Here we set the foreground color to purple and then add some empty paddings around the text. The border modifier is used to define the border's width and color. Please feel free to alter the value of the width parameter to see how it works.

Let me give you another example. Let's say, a designer shows you the following button design. How are you going to implement it with what you've learned? Before you read the next paragraph, please give yourself a few minutes to figure out the solution.

Figure 9. A button with both background and border
Figure 9. A button with both background and border

Okay, here is the code you need:

Text("Hello World")
    .fontWeight(.bold)
    .font(.title)
    .padding()
    .background(Color.purple)
    .foregroundColor(.white)
    .padding(10)
    .border(Color.purple, width: 5)

We use two padding modifiers to create the button design. The first padding, together with the background modifier, is for creating a button with padding and purple background. The padding(10) modifier adds extra paddings around the button and the border modifier specifies to paint a rounded border in purple.

Let's see a more complex example. What if you want to design the button with rounded borders like this?

Figure 10. A button with a rounded border
Figure 10. A button with a rounded border

SwiftUI comes with a modifier named cornerRadius that lets you easily create rounded corners. To render the button's background with rounded corners, you can simply use the modifier and specify the corner radius like this:

.cornerRadius(40)

For the border with rounded corners, it'll take a little bit of work since the border modifier doesn't allow you to create rounded corners. So, what we need to do is to draw a border and overlay it on the button. Here is the final code:

Text("Hello World")
    .fontWeight(.bold)
    .font(.title)
    .padding()
    .background(Color.purple)
    .cornerRadius(40)
    .foregroundColor(.white)
    .padding(10)
    .overlay(
        RoundedRectangle(cornerRadius: 40)
            .stroke(Color.purple, lineWidth: 5)
    )

The overlay modifier lets you overlay another view on top of the current view. In the code, what we did was to draw a border with rounded corners using the stroke modifier of the RoundedRectangle object. The stroke modifier allows you to configure the color and line width of the stroke.

To access the full content and the complete source code, please get your copy at https://www.appcoda.com/swiftui.

results matching ""

    No results matching ""