I have a SwiftUI view that presents a number of GridRows
in a Grid
. Each row has 2 columns, the left column is aligned right, and the right column is aligned left. Each row contains a title (left column) and data field (right column).
TextFields
, and Pickers
behave as I expect, aligning to the left side of their column. But the DatePicker
will only align to the right side of its column.
Things I've tried that didn't work:
Spacer()
after the DatePicker
DatePicker
inside VStack(alignment: .leading)
within its GridRow
Anyone know how to move the DatePicker to align with the rest of the rows on the left?
Below is a view to illustrate
import SwiftUI
struct ContentView: View {
@State var name = ""
@State var date = Date()
@State var house = Int()
var body: some View {
NavigationStack {
ScrollView {
VStack(alignment: .leading) {
Grid(alignment: .leading) {
GridRow {
Text("Name \(Image(systemName: "person")):")
.font(.headline)
.gridColumnAlignment(.trailing)
TextField("Full name", text: $name)
.font(.body)
.padding(.horizontal, 10)
.padding(.vertical, 5)
.background(Color(UIColor.systemBackground))
.cornerRadius(8)
.gridColumnAlignment(.leading)
}
GridRow {
Text("Birthdate \(Image(systemName: "calendar")):")
.font(.headline)
DatePicker("", selection: $date, displayedComponents: .date)
}
GridRow {
Text("House \(Image(systemName: "house")):")
.font(.headline)
Picker("", selection: $house) {
Text("Gryffindor").tag(1)
Text("Slytherin").tag(2)
Text("Ravenclaw").tag(3)
Text("Hufflepuff").tag(4)
}
}
}
}
.padding(10)
.background(RoundedRectangle(cornerRadius: 10)
.fill(Color.gray
.gradient
.opacity(0.15)))
}
.padding(.horizontal)
.navigationTitle("Add Wizard Info")
.navigationBarTitleDisplayMode(.inline)
}
}
}
By inspecting the UI hierarchy, SwiftUI seems to put the date picker inside an HStack
, consisting of the label (showing an empty string in your case), a Spacer
, and a UIViewRepresentable
representing a UIDatePicker
.
(Red is the HStack
, blue is the Spacer
, black is the UIViewRepresentable
wrapping a UIDatePicker
. The label shows "" so is not visible.)
The Spacer
makes the whole thing "expand" horizontally, pushing the date picker to the right.
Just add .fixedSize()
to the DatePicker
, so that it is at its ideal size.
DatePicker("", selection: $date, displayedComponents: .date)
.fixedSize()
Now the Spacer
won't expand, but note that there is still a bit of spacing:
That is the default spacing that HStack
adds between the label and the date picker. If you want to remove that as well, you can take advantage of the fact that DatePicker
counts as a "labeled content" (not sure if this is guaranteed), and apply your own .labeledContentStyle
:
DatePicker("", selection: $date, displayedComponents: .date)
.labeledContentStyle(ContentOnlyStyle())
// this removes the label, and only shows the content (in this case, the date picker)
struct ContentOnlyStyle: LabeledContentStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.content
}
}
Now you don't even need fixedSize
.