1

I am building a simple form in SwiftUI for macOS but once I add a picker the layout is screwed up.

This is my code:

var body: some View {
        GeometryReader { geometry in
            Form {
                HStack {
                    Text("Label")
                        .frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)

                    TextField("", text: $field1)
                }

                HStack {
                    Text("Long Label")
                        .frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
                    TextField("", text: $field2)
                }

//                HStack {
//                    Text("Picker")
//                        .frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
//
//                    Picker("", selection: $selectedColor) {
//                        ForEach(colors, id: \.self) {
//                            Text($0)
//                        }
//                    }
//                }

            }
            .padding(20)
        }
    }
}

and this is the form which comes out:

enter image description here

Adding a simple picker, the layout becomes:

enter image description here

and I am not able to keep all the labels aligned. I have tried to add a frame to the picker and to the HStack but nothing helps.

I have also tried with:

 Picker(selection: $selectedColor, label: EmptyView() {
    ...
 }

and:

 Picker(selection: $selectedColor, label: Text("Picker") {
                        ...
 }

getting the same result.

How do I keep the labels aligned?

Fab
  • 1,378
  • 1
  • 14
  • 33

2 Answers2

4

Add labelIsHidden() to your Picker:

 HStack {
   Text("Picker").frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
                    
   Picker("", selection: $selectedColor) {
                        ForEach(colors, id: \.self) {
                            Text($0)
                        }
   }.labelIsHidden()
}
andrewbuilder
  • 3,373
  • 1
  • 23
  • 43
jnpdx
  • 35,475
  • 5
  • 43
  • 61
1

I think @jnpdx's answer is better but this is another way.

  • Read comments in the code:
    • Embed 3 HStacks into a VStack
    • Change minWidth to 0.24
import SwiftUI

struct ContentView: View {
  var body: some View {
    GeometryReader { geometry in
      Form {
        // Embed 3 HStacks into a VStack
        VStack {
          HStack {
            Text("Label")
              .frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
            TextField("label", text: .constant("")).labelStyle(IconOnlyLabelStyle())
          }
          
          HStack {
            Text("Long label")
              .frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
            TextField("long Label", text: .constant(""))
          }
          
          HStack {
            Text("Picker")
              // Change minWidth to 0.24
              .frame(minWidth: 0.24 * geometry.size.width, alignment: .leading)
            Picker("", selection: .constant(Color.red)) {
              ForEach([Color.red, Color.green, Color.blue], id: \.self) {
                Text($0.description)
              }
            }
          }
        }
        
      }
      .padding(20)
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

enter image description here

Thai D. V.
  • 403
  • 1
  • 5
  • 10
  • This works as well, but not in my case. I simplified my actual code for the question, my form contains sections and my picker is inside the section. This solution screws up the next section. – Fab Mar 10 '21 at 06:53