Home > Enterprise >  Applying padding to SwiftUI Picker with menu style is causing multiline text
Applying padding to SwiftUI Picker with menu style is causing multiline text

Time:11-10

I have a Picker with menu style presenting a label with an icon and text. When applying a padding to any views containing the picker, the picker will behave as though there is not enough space and run to multiple lines even though there is enough space.

Sample Code

struct ContentView: View {
    let options = [
        "Some Long Text"
    ]

    private var selectedOption: Binding<String> =
        .constant("Some Long Text")

        var body: some View {
            HStack {
                Text("Some Text")
                Picker("Work Type", selection: selectedOption) {
                    ForEach(self.options, id: \.self) {
                        Label($0, systemImage: "pencil.tip.crop.circle")
                    }
                }.pickerStyle(.menu)
            }
        }
}

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

enter image description here

CodePudding user response:

This seems like intended behavior to me. Because of the padding applied around the HStack (specifically at the horizontal edges) there is not enough space to render the form label on one line. If you were to change the size of the screen (for example using an iPad simulator or using landscape mode) the label would have enough room and be displayed on one line. I tested this code on an iPad simulator and it worked as expected.

If you want to force the label text to be rendered on one line, use fixedSize(horizontal:vertical:). Though this can lead to unexpected behavior.

Picker("Work Type", selection: selectedOption) {
    ForEach(self.options, id: \.self) {
        Label($0, systemImage: "pencil.tip.crop.circle")
    }
}
.pickerStyle(.menu)
.fixedSize(horizontal: true, vertical: false)

CodePudding user response:

This might be a layout bug in SwiftUI. There is clearly enough space to put it all in one line, even with the padding. You may want to file a bug report to Apple.

However, you can easily fix this by applying the fixedSize() modifier to your Picker:

Picker("Work Type", selection: selectedOption) {
    // ...
}
.pickerStyle(.menu)
.fixedSize(horizontal: true, vertical: false)

This will make sure that the Picker doesn't concern itself with external sizing requirements, ignores the proposed with and just uses renders with its ideal size.

Please note that this might lead to unintended behavior. For example, when the user chooses a bigger font size in accessibility settings, the text in the Picker will never break and might be rendered off-screen. So make sure to think through all your use cases.


PS: You can also use a Menu instead of a Picker with .menu style. Of course, you won't get the selection behavior for free and have to do it manually, but it doesn't have this layout bug.

  • Related