I have created a custom picker that is larger than the native SwiftUI picker. This picker is being used on an iPad which is why I need it larger than usual. When I use the picker, I can't tap on the padding portions. The picker is only opened when I tap directly in the horizontal center of my picker. I have read about using a .frame()
modifier to change the tappable area of things like buttons, but that does not seem to work here when I try to add a frame modifier to the base Picker itself. Here is an image of the additional area (in orange) I would like to make tappable
And here is my code:
import SwiftUI
struct CustomPickerStyle: ViewModifier {
var labelText: String
var width: CGFloat
func body(content: Content) -> some View {
Menu {
content
} label: {
HStack {
if let labelText = labelText {
Text(labelText)
.font(.title2)
.fontWeight(.bold)
Spacer()
Image(systemName: "triangle.fill")
.resizable()
.frame(width: 12, height: 8)
.rotationEffect(.degrees(180))
}
}
}
.frame(maxWidth: width, alignment: .leading)
.padding()
.background(.white)
.overlay(
RoundedRectangle(cornerRadius: 3)
.stroke(.gray, lineWidth: 2)
)
}
}
extension View {
func customPickerStyle(labelText: String, width: CGFloat) -> some View {
self.modifier(CustomPickerStyle(labelText: labelText, width: width))
}
}
struct CustomPicker: View {
enum Flavor: String, CaseIterable, Identifiable {
case chocolate, vanilla, strawberry
var id: Self { self }
}
@State private var selectedFlavor: Flavor = .chocolate
var body: some View {
Picker("Flavor", selection: $selectedFlavor) {
Text("Chocolate").tag(Flavor.chocolate)
Text("Vanilla").tag(Flavor.vanilla)
Text("Strawberry").tag(Flavor.strawberry)
}
.customPickerStyle(labelText: selectedFlavor.rawValue, width: 200)
}
}
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
CustomPicker()
}
}
CodePudding user response:
Just move your padding and background stylings directly inside the label:
struct CustomPickerStyle: ViewModifier {
var labelText: String
var width: CGFloat
func body(content: Content) -> some View {
Menu {
content
} label: {
HStack {
if let labelText = labelText {
Text(labelText)
.font(.title2)
.fontWeight(.bold)
Spacer()
Image(systemName: "triangle.fill")
.resizable()
.frame(width: 12, height: 8)
.rotationEffect(.degrees(180))
}
}
.frame(maxWidth: width, alignment: .leading)
.padding()
.background(.white)
.overlay(
RoundedRectangle(cornerRadius: 3)
.stroke(.gray, lineWidth: 2)
)
}
}
}