KANAYO AUGUSTIN UG
KANAYO AUGUSTIN UG

Reputation: 2188

Tap outside picker text not opening picker menu

I have a Picker like this

Picker ("", selection: $itemIndex){
    ForEach (0..<items.count, id: \.self){ index in
        Text(items[index])
    }
}
.frame(maxWidth: .infinity)
.background(.red)

The issue is that the picker extends to the screen width but the text displaying on the Picker is not that lengthy, maybe about 1/20 of the Picker length

Now when I click on the text, the Picker menu opens up, but when I click outside the text, still within the picker visibility, the menu don't open.

enter image description here

In the image above, when I tap on the red side, the menu opens up, but when I tap on both green sides it doesn't

Do anyone have an idea why this is happening?

Note: the picker is not in a Form or a NavigationController

Upvotes: 0

Views: 392

Answers (2)

KANAYO AUGUSTIN UG
KANAYO AUGUSTIN UG

Reputation: 2188

Okay... So through the help of this question, I was able to customize my own Picker style. Below is the code to achieve this

struct CustomPickerStyle: ViewModifier {
    
    @Binding var index: Int
    var items: [String]
    var font: SwiftUI.Font
    var padding: CGFloat
    
    func body(content: Content) -> some View {
        Menu {
            content
        } label: {
            HStack {
                if let labelText = items[index] {
                    Text(labelText)
                        .font(font)
                    Spacer()
                    Image(systemName: "triangle.fill")
                        .resizable()
                        .frame(width: 12, height: 8)
                        .rotationEffect(.degrees(180))
                }
            }
            .padding(padding)
            .frame(alignment: .leading)
            .background(Colors.white)
        }
    }
    
}

extension View {
    
    func customPickerStyle(index: Binding<Int>, items: [String], font: SwiftUI.Font, padding: CGFloat) -> some View {
        self.modifier(CustomPickerStyle(index: index, items: items, font: font, padding: padding))
    }
}

And I this is how I used it in my UI

Picker("", selection: $itemIndex){
    ForEach(0..<items.count, id: \.self){ index in
        Text(items[index])
    }
}
.customPickerStyle(index: $itemIndex, items: items, font: .system(size: 17), padding: 10)
.frame(width: UIScreen.main.bounds.width - 50)
.overlay(RoundedRectangle(cornerRadius: 10.0).stroke(.blue, lineWidth: 1.0))

And here is the result

enter image description here

Upvotes: 1

Asperi
Asperi

Reputation: 258365

I assume you wanted this

Picker ("", selection: $itemIndex){
    ForEach (0..<items.count, id: \.self) { index in
        Text(items[index])
           .frame(maxWidth: .infinity)    // << here !!
    }
}
.background(.red)

or this if you told about Menu

    Menu {

      // content here

    } label: {
        Text("Menu")
            .frame(maxWidth: .infinity)    // << here !!
    }

the general rule is - give space for label which is actually shown, instead of containing control, because hit testing is usually set up by intrinsic content.

Upvotes: 0

Related Questions