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,468
  • 1
  • 16
  • 37

3 Answers3

5

Add labelsHidden() to your Picker:

 HStack {
   Text("Picker").frame(minWidth: 0.25 * geometry.size.width, alignment: .leading)
                    
   Picker("", selection: $selectedColor) {
                        ForEach(colors, id: \.self) {
                            Text($0)
                        }
   }.labelsHidden()
}
Eimantas
  • 48,927
  • 17
  • 132
  • 168
jnpdx
  • 45,847
  • 6
  • 64
  • 94
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.
  • 483
  • 1
  • 5
  • 11
  • 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
0

This answer is much better than accepted answer: https://stackoverflow.com/a/73946863/202179

In short there is a LabeledContent for that purpose now.

Ivan Ičin
  • 9,672
  • 5
  • 36
  • 57