NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

Polishing designs with fonts and colors

Paul Hudson    @twostraws   

Updated for Xcode 14.2

We’ll add some more to our design in just a moment, but first let’s pause and make what we have look better.

In ItemRow.swift, our menu item’s name is clearly the most important thing in each row, but it has the same font size as the price below. We can bring it up in size and weight by using the font() modifier, which accepts any of Apple’s Dynamic Type sizes.

So, something like this will make it stand out:

Text(item.name)
    .font(.headline)

As for the picture, it looks OK as it is, but with a little love it would look better. For example, we could apply a clipShape() modifier and ask it to be clipped to a circle shape:

Image(item.thumbnailImage)
    .clipShape(Circle())

Or we could apply a clipShape() modifier, then add an overlay() modifier so we place a shape on top of our image. For example, this will add a circle over the image, then give that circle a 2-point gray border:

Image(item.thumbnailImage)
    .clipShape(Circle())
    .overlay(Circle().stroke(.gray, lineWidth: 2))

OK, that’s enough styling – let’s look at something more complex.

If you look in menu.json you’ll see that each menu item has a string array of restrictions: “G” for containing gluten, “N” for containing nuts, “V” for being vegetarian friendly, and so on. We can use that to create colored icons representing what’s in the food at a glance, showing zero or more of them in each row as appropriate.

First, we need a dictionary of colors that we’ll use for each restriction type. Add this property to ItemRow:

let colors: [String: Color] = ["D": .purple, "G": .black, "N": .red, "S": .blue, "V": .green]

Second, we need to loop over all the restrictions and put each one into a text view. Put this after the VStack containing the name and cost:

ForEach(item.restrictions) { restriction in
    Text(restriction)
}

Now we have a problem: that code won’t compile. As I mentioned earlier, we can put arrays into a ForEach as long as SwiftUI knows how to identify each item in the array uniquely. We solved that by making our sections and items conform to the Identifiable protocol, which uses the id property to identify items.

Here, though, we have an array of strings, so we can’t make them conform to Identifiable. Instead, we need something else: we need to tell Swift that the string itself is the identifier for each item. This can be done using the id parameter for ForEach, passing in \.self as its only parameter, like this:

ForEach(item.restrictions, id: \.self) { restriction in
    Text(restriction)
}

And now you should see the text “G” and “V” next to our example item in the Xcode preview.

That’s pretty dull, though, so let’s spice it up with some modifiers:

Text(restriction)
    .font(.caption)
    .fontWeight(.black)
    .padding(5)
    .background(colors[restriction, default: .black])
    .clipShape(Circle())
    .foregroundColor(.white)

That will use a small, bold font with white text and a colored background, add a circular clipping shape, and add a little space around it so the text circles aren’t so near.

A SwiftUI list row, showing a food photo, its name, and price, along with circles showing what food restrictions it has.

We’re going to do one more thing before we’re done with the design of this item row: we’re going to force the restriction text to be spaced apart from the rest of the row. SwiftUI has a dedicated view for this called Spacer, and I’d like you to place it just before the ForEach for our restrictions, like this:

Spacer()

ForEach(item.restrictions, id: \.self) {

That will automatically take up all available free space, meaning that our picture will now be on the far left and the restrictions on the far right.

Go ahead and run the project now and I think you’ll agree it looks great! Now think about how you might have accomplished all that using a UITableViewCell – it would take more code than you expect!

Further reading

Hacking with Swift is sponsored by Essential Developer

SPONSORED From March 20th to 26th, you can join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer!

Click to save your free spot now

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

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI 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 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 Beyond Code

Was this page useful? Let us know!

Average rating: 4.7/5

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.