Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Section header inside a Menu for a Picker not visible

Tags:

ios

swiftui

I'm trying to have a Section header inside a Menu for a Picker in mit SwiftUI application, but it does not show up:

enum Filter {
    case upcoming, past
}

struct ContentView: View {
    @State var filter = Filter.upcoming
    
    var body: some View {
        Menu("Example") {
            Section("Foo") {
                Text("Bar")
            }
            
            Section("Filter") {
                Picker(selection: $filter, label: Text("Filter options")) {
                    Text("Upcoming events").tag(Filter.upcoming)
                    Text("Past events").tag(Filter.past)
                }
            }
            
            Section("Order") {
                Button("Ascending") {}
                Button("Descending") {}
            }
        }
        .menuOrder(.fixed)
    }

}

Any idea how to get a section header above a Picker?

enter image description here

like image 888
Slevin Avatar asked Oct 31 '25 14:10

Slevin


2 Answers

Starting with iOS 18.0, you can use the labelsVisibility(_:) modifier to ensure a section header is displayed for a Picker within a Menu.

enum Filter {
    case upcoming, past
}

struct ContentView: View {
    @State var filter = Filter.upcoming
    
    var body: some View {
        Menu("Example") {
            Section("Foo") {
                Text("Bar")
            }
            
            Picker(selection: $filter, label: Text("Filter options")) {
                Text("Upcoming events")
                    .tag(Filter.upcoming)
                Text("Past events")
                    .tag(Filter.past)
            }
            .labelsVisibility(.visible)
            
            Section("Order") {
                Button("Ascending") {}
                Button("Descending") {}
            }
        }
        .menuOrder(.fixed)
    }
}
screenshot
like image 103
Imanou Petit Avatar answered Nov 03 '25 03:11

Imanou Petit


It seems that when the picker style is the default of .inline then the section header is always hidden.

Here are two possible workarounds.

1. Use picker style .menu

The section header is shown if you change the picker style to .menu. But then the picker is collapsed. So it's a compromise.

Section("Filter") {
    Picker(selection: $events.filter, label: Text("Filter options")) {
        Text("Upcoming events").tag(EventListRequest.Filter.upcoming)
        Text("Past events").tag(EventListRequest.Filter.past)
    }
    .pickerStyle(.menu)
}

Screenshot

2. Use regular buttons with a custom LabelStyle

As another possible workaround, the individual picker items can simply be listed as regular buttons inside the Section. A custom LabelStyle can then be used to show a checkmark against the item that is selected.

This gives almost the same appearance as an inline Picker, except that the checkmark is on the right instead of on the left.

struct MyLabelStyle: LabelStyle {
    let isSelected: Bool
    func makeBody(configuration: Configuration) -> some View {
        if isSelected {
            configuration.icon
        }
        configuration.title
    }
}
Section("Filter") {
    Button { events.filter = .upcoming } label: {
        Label("Upcoming events", systemImage: "checkmark")
            .labelStyle(MyLabelStyle(isSelected: events.filter == .upcoming))
    }
    Button { events.filter = .past } label: {
        Label("Past events", systemImage: "checkmark")
            .labelStyle(MyLabelStyle(isSelected: events.filter == .past))
    }
}

CustomLabel

like image 37
Benzy Neez Avatar answered Nov 03 '25 03:11

Benzy Neez



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!