I have a following code with Picker in SwiftUI on iOS:
enum Something: String, CaseIterable {
case one
case two
case three
}
struct ContentView: View {
@State private var something: Something = .one
var body: some View {
VStack {
HStack {
Text("Something")
Spacer()
Picker(selection: $something) {
ForEach(Something.allCases, id: \.self) { name in
Text("\(name)")
}
} label: {}
.pickerStyle(.menu)
.frame(minWidth: 180, alignment: .trailing)
.background(.yellow)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
Spacer()
}
.tint(.red)
.padding()
}
}
which looks like below:
Is there any way to make the whole yellow area tappable so that user can click anywhere on the yellow shape to expand it (and not only on the "one" text as in this example)? The label parameter of the picker is not really used on iOS so we cannot put the rectangle inside it and use contentShape modifier as with some other UI elements. Also I cannot see any way to programaticaly expand the picker so doing that manually with .onTapGesture also seems impossible. Is there any other way to do it and keep the original Picker look exactly as it is on the screenshot?
The yellow frame you have added around the Picker
is not part of the picker, so it does not trigger the picker selection when tapped.
If you want to change the way the picker displays the current selection, you probably need to define your own PickerStyle
. However, the functions of this protocol are not public, so that's not really an option.
As a workaround, you can wrap the Picker
with a Menu
, then you can style the label of the Menu
any way you like. The label is receptive to taps:
LabeledContent("Something") {
Menu {
Picker(selection: $something) {
ForEach(Something.allCases, id: \.self) { name in
Text("\(name)")
}
} label: {}
} label: {
HStack(spacing: 4) {
Text("\(something)")
Image(systemName: "chevron.up.chevron.down")
.imageScale(.small)
}
.padding(.vertical, 7)
.padding(.horizontal, 12)
.frame(minWidth: 180, alignment: .trailing)
.background(.yellow, in: .rect(cornerRadius: 8))
}
}
.tint(.red)