NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

Adding a segmented control for tip percentages

Paul Hudson    @twostraws   

Now we’re going to add a second picker view to our app, but this time we want something slightly different: we want a segmented control. This is a specialized kind of picker that shows a handful of options in a horizontal list, and it works great when you have only a small selection to choose from.

Our form already has two sections: one for the amount and number of people, and one where we’ll show the final result – it’s just showing checkAmount for now, but we’re going to fix it soon.

In the middle of those two sections I’d like you to add a third to show tip percentages:

Section {
    Picker("Tip percentage", selection: $tipPercentage) {
        ForEach(0 ..< tipPercentages.count) {
            Text("\(self.tipPercentages[$0])%")
        }
    }
}

That counts through all the options in our tipPercentages array, converting each one into a text view. Just like the previous picker, SwiftUI will convert that to a single row in our list, and slide a new screen of options in when it’s tapped.

Here, though, I want to show you how to use a segmented control instead, because it looks much better. So, please add this modifier to the tip picker:

.pickerStyle(SegmentedPickerStyle())

That should go at the end of the picker’s closing brace, like this:

Section {
    Picker("Tip percentage", selection: $tipPercentage) {
        ForEach(0 ..< tipPercentages.count) {
            Text("\(self.tipPercentages[$0])%")
        }
    }
    .pickerStyle(SegmentedPickerStyle())
}

If you run the program now you’ll see things are starting to come together: users can now enter the amount on their check, select the number of people, and select how much tip they want to leave – not bad!

But things aren’t quite what you think. One problem app developers face is that we take for granted that our app does what we intended it to do – we designed it to solve a particular problem, so we automatically know what everything means.

Try to look at our user interface with fresh eyes, if you can:

  • “Amount” makes sense – it’s a box users can type a number into.
  • “Number of people” is also pretty self-explanatory.
  • The label at the bottom is where we’ll show the total, so right now we can ignore that.
  • That middle section, though – what are those percentages for?

Yes, we know they are to select how much tip to leave, but that isn’t obvious on the screen. We can – and should do better.

One option is to add another text view directly before the segmented control, which we could do like this:

Section {
    Text("How much tip do you want to leave?")

    Picker("Tip percentage", selection: $tipPercentage) {
        ForEach(0 ..< tipPercentages.count) {
            Text("\(self.tipPercentages[$0])%")
        }
    }
    .pickerStyle(SegmentedPickerStyle())
}

That works OK, but it doesn’t look great – it looks like it’s an item all by itself, rather than a label for the segmented control.

A much better idea is to modify the section itself: SwiftUI lets us add views to the header and footer of a section, which in this instance we can use to add a small explanatory prompt. In fact, we can use the same text view we just created, just moved up to be the section header rather than a loose label inside it.

Here’s how that looks in code:

Section(header: Text("How much tip do you want to leave?")) {
    Picker("Tip percentage", selection: $tipPercentage) {
        ForEach(0 ..< tipPercentages.count) {
            Text("\(self.tipPercentages[$0])%")
        }
    }
    .pickerStyle(SegmentedPickerStyle())
}

It’s a small change to the code, but I think the end result looks a lot better – the text now looks like a prompt for the segmented control directly below it.

Hacking with Swift is sponsored by Instabug

SPONSORED Are you tired of wasting time debugging your Swift app? Instabug’s SDK is here to help you minimize debugging time by providing you with complete device details, network logs, and reproduction steps with every bug report. All data is attached automatically, and it only takes a line of code to setup. Start your free trial now and get 3 months off exclusively for the Hacking with Swift Community.

Start your free trial!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Subscribe to Hacking with Swift+

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.8/5