I'm creating a form with multiple sections in SwiftUI. Each section contains several text fields, each with a label.
I'd like to align the leading edges of the text fields with each other and also with the center of the view.
I'm able to align the leading edges of the text fields within a section using the following:
extension HorizontalAlignment {
private struct LeadingEdgeAlignment: AlignmentID {
/// A custom alignment for leading edges.
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[.leading]
}
}
/// A guide for aligning leading edges.
static let leadingEdge = HorizontalAlignment(LeadingEdgeAlignment.self)
}
struct ContentView: View {
var body: some View {
Form {
Section(header: Text("Section One")) {
VStack(alignment: .leadingEdge) {
HStack {
Text("Primary")
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Secondary")
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
Section(header: Text("Section Two")) {
VStack(alignment: .leadingEdge) {
HStack {
Text("Milk")
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Cheesecake")
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
}
}
}
However, so far all my attempts to create alignment guides that span sections have failed.
How does one align views across form sections?
Since you are splitting in half one way to do it is to have even columns. But you have to handle the significant difference in text length
struct AlignedSectionView: View {
let columns = [GridItem(), GridItem()]
var body: some View {
Form {
Section(header: Text("Section One")) {
//Divide the section in half
LazyVGrid(columns: columns, alignment: .leadingEdge) {
HStack {
Text("Primary")
//Push the TextField to the Halfway point
Spacer()
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
//Fill in the column
Spacer()
HStack {
Text("Secondary")
Spacer()
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
Section(header: Text("Section Two")) {
//Divide the section in half
LazyVGrid(columns: columns, alignment: .leadingEdge) {
HStack {
Text("Milk")
//Push the TextField to the Halfway point
Spacer()
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
//Fill in the column
Spacer()
HStack {
Text("Cheesecake")
//So it doesnt go to the next line
.lineLimit(1)
Spacer()
TextField("", text: .constant(""))
.frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
.alignmentGuide(.leadingEdge) { $0[HorizontalAlignment.leading] }
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
}
}
//One way of dealing with the difference in text sizes is to allow the text to get smaller to fit
.minimumScaleFactor(0.9)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With