0

If I place a Picker or a Toggle in a SwiftUI Form, the associated label is always visible:

enter image description here

But for a TextField, the label is only shown while the field is empty:

enter image description here

And as soon as I start to fill in the TextField, the label disappears.

enter image description here

So now I have no context for what the TextField is meant for.

This would not be a problem if the TextField content is self explanatory, but I have a form with multiple TextFields used to input numerical values, and once they are filled in I have no context for differentiating between each number.

Is there any way to make a SwiftUI TextField behave like a Picker or Toggle, and have the label permanently displayed?


Update:

After trying out Benzy's answer of using LabeledContent, I get this sort of result when I have multiple fields. As you can see the alignment of the TextFields themselves depends on the length of the text in the LabeledContent. I'd prefer to align the TextFields.

enter image description here

1 Answer 1

1

Try wrapping the TextField as LabeledContent:

Form {
    Section("Creator") {
        LabeledContent("Name") {
            TextField("Name", text: $creator, prompt: Text("Name"))
        }
    }
}

Screenshot Screenshot


You might prefer to supply an empty prompt and then add styling to the label, for example, to style it like a prompt:

LabeledContent {
    TextField("Name", text: $creator, prompt: Text(""))
} label: {
    Text("Name")
        .foregroundStyle(.secondary)
}

Screenshot Screenshot


EDIT You were asking in a comment, how to align multiple text fields.

A simple way would be to set a fixed width on the labels. However, if you want the labels to be as wide as the widest label, you could use a ZStack to determine the footprint for the labels:

private let allLabels = ["Street", "City", "State", "Country"]
private var labelFootprint: some View {
    ZStack {
        ForEach(allLabels, id: \.self) { label in
            Text(LocalizedStringKey(label))
        }
    }
    .hidden()
}

The visible labels can then be shown as an overlay over the footprint. For example:

LabeledContent {
    TextField("Street", text: $street)
} label: {
    labelFootprint.overlay(alignment: .leading) {
        Text("Street")
    }
}

Screenshot

Sign up to request clarification or add additional context in comments.

4 Comments

I'll try this shortly. I prefer your first option over the second option because visually the second option doesn't match what I see with the label for the Picker and Toggle.
If I have a form with multiple fields, and I use the LabeledContent as per your example, is the any way to set a consistent width of the labels across all the fields, so that the actual TextFields are left aligned on some point, even if the text of the LabeledContent itself is staggered?
See my update after trying your suggestion.
Answer updated with a way to align the fields

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.