How to fix SwiftUI picker not displaying horizontally centered?

67 views Asked by At

I created a simple Picker like so:

struct ContentView: View {
    private let options = ["Action", "Comedy", "Drama", "Horror", "Zombie"]
    @State var selection = "Action"
    var body: some View {
        VStack {
            Picker("Select Genre", selection: $selection) {
                ForEach(options, id: \.self) { item in
                    HStack {
                        Text(item)
                        Image(systemName: "heart.fill")
                    }
                }
            }
        }
        .padding()
    }
}

enter image description here

When it displays I can see that it is slightly left aligned in the screen. Is there any way to fix this? Also, is there any way to detect when the Picker is showing its options?

1

There are 1 answers

0
Benzy Neez On BEST ANSWER

The options menu moves with the Picker, so by adding padding to the Picker you can center it. But then, the Picker itself is a bit off-center. You could mask this by showing the same Picker as an overlay, without the padding. If you apply .allowsHitTesting(false) to the overlay then it becomes inactive, so when you tap it, the tap passes through and you get the menu from the base Picker.

This kind of workaround may break if the layout changes in a future iOS version. So I would only suggest using it for iOS versions that you have actually tested.

Like this:

private var thePicker: some View {
    Picker("Select Genre", selection: $selection) {
        ForEach(options, id: \.self) { item in
            HStack {
                Text(item)
                Image(systemName: "heart.fill")
            }
        }
    }
}

var body: some View {
    VStack {
        if #available(iOS 17.3, *) {
            thePicker
        } else if #available(iOS 17.0, *) {
            thePicker
                .padding(.leading, 16)
                .overlay {
                    thePicker
                        .background(Color(UIColor.systemBackground))
                        .allowsHitTesting(false)
                }
        } else {
            thePicker
        }
    }
    .padding()
}

Screenshot