Home > Mobile >  Is there a way to increase the tappable area of a Picker in SwiftUI?
Is there a way to increase the tappable area of a Picker in SwiftUI?

Time:03-09

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)
            )
        }
    }
}
  • Related