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

How to align form text and controls neatly with LabeledContent

Paul Hudson    @twostraws   

Updated for Xcode 14.2

SwiftUI’s forms do a great job of making many views look good out of the box, but sometimes you need a little extra control to get exactly the right result – aligning text correctly, labelling custom views, or aligning controls that don’t carry labels such as Slider.

In its simplest form, using LabeledContent is similar to using the badge() modifier:

Form {
    LabeledContent("This is important", value: "Value goes here")
}

Download this as an Xcode project

This will place the title on the leading edge of the screen and the value on the trailing edge. The alignment will automatically adjust depending on your platform: iOS left aligns the title and right aligns the value, whereas macOS right aligns the title and left aligns the value. This is particularly important for forms on macOS, where other view types such as TextField and Toggle automatically align their title and value, whereas Slider would not.

On iOS this use of LabeledContent gives the same result as using Text("This is important").badge("Value goes here"), but the real power of LabeledContent is that it can take any view, whereas badges accepts only text and numbers.

So, we could use LabeledContent to show an image by passing a custom content closure:

LabeledContent("This is important") {
    Image(systemName: "exclamationmark.triangle")
}

Download this as an Xcode project

But more importantly, we can also use it with any views that would not normally have a label, such as Slider:

struct ContentView: View {
    @State private var brightness = 0.5

    var body: some View {
        Form {
            LabeledContent {
                Slider(value: $brightness)
            } label: {
                Text("Brightness")
            }
        }
    }
}

Download this as an Xcode project

This is particularly important on macOS, because it was place the label on the left-hand side of the form and the slider on the right.

Important: At the time of writing, some SwiftUI views such as Stepper will not use the title of your LabeledContent for VoiceOver. This makes them rather opaque in terms of accessibility support, so you should use them carefully.

If the title of your LabeledContent includes two pieces of text, iOS will automatically render the second text in a smaller, lighter font, making it look like a subtitle:

Form {
    LabeledContent {
        Text("Value")
    } label: {
        Text("Title")
        Text("Subtitle")
    }
}

Download this as an Xcode project

In fact, it supports up to four pieces of text using this approach, with each one rendered smaller and lighter:

Form {
    LabeledContent {
        Text("Value")
    } label: {
        Text("Title")
        Text("Subtitle")
        Text("Subsubtitle")
        Text("Subsubsubtitle")
    }
}

Download this as an Xcode project

Tip: If you apply the labelsHidden() modifier to any LabeledContent, the label title will be hidden while leaving the content visible.

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

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!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.