Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aligning views across form sections

Tags:

swift

swiftui

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?

like image 541
sbooth Avatar asked Sep 15 '26 01:09

sbooth


1 Answers

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)
    }
}
like image 176
lorem ipsum Avatar answered Sep 17 '26 20:09

lorem ipsum



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!