How to fix a Picker navigation works only when I long press a link

Viewed 261

I'm currently developing an application using SwiftUI.

When I use a onTapGesture at Form in NavigationView, navigation of Picker the inside doesn't work.

It works but only when I long-press a link like a LongPressGesture.

If I don't use onTapGesture, the navigation of Picker works, as usual, But in that case, I can not close a keyboard when I use TextField choosing numberPad as keyboardType...

How could I solve this problem?


Here is a code:

OnTapGestureTest.swift

import SwiftUI

struct OnTapGestureTest: View{
    
    @State var inputNo:String = ""
    @State var selectNo:Int = 0
    
    var body: some View {
        NavigationView{
            Form{
                TextField("InputNo", text: $inputNo)
                    .keyboardType(.numberPad)
                
                Picker(selection:$selectNo, label: Text("SelectNo")){
                    Text("0").tag(0)
                    Text("1").tag(1)
                    Text("2").tag(2)
                    Text("3").tag(3)
                    Text("4").tag(4)
                    Text("5").tag(5)
                    
                }
            }
            .onTapGesture {
                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
            }
        }
    }
}

UPDATED

I tried to solve my question by referencing here.

*I want to close keyboard only on Tap outside (without handling drags) in iOS 13.0

SceneDelegate.swift

...
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
...
        let tapGesture = UITapGestureRecognizer(target: window, action:#selector(UIView.endEditing))
        tapGesture.requiresExclusiveTouchType = false
        tapGesture.cancelsTouchesInView = false
        tapGesture.delegate = self 
        window?.addGestureRecognizer(tapGesture)
    }
...

But it still doesn't work well... Do I need to do some more things? misunderstand the answer?


Xcode: Version 12.0.1

iOS: 13.0

1 Answers

You could add the tap gesture globally, with the help of UIWindow:

extension UIApplication {
    
    func addTapGestureRecognizer() {
        guard let window = windows.first else { return }
        let tapGesture = UITapGestureRecognizer(target: window, action: #selector(UIView.endEditing))
        tapGesture.requiresExclusiveTouchType = false
        tapGesture.cancelsTouchesInView = false
        tapGesture.delegate = self
        window.addGestureRecognizer(tapGesture)
    }
}


extension UIApplication: UIGestureRecognizerDelegate {
    
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true 
    }
}

In your main: (The idea: as soon as your app launches, this tapGesture is added to the window)

@main
struct YourApp: App {
    
    ...
    
    var body: some Scene {
        WindowGroup {
            //Your initial view
                .onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
        }
    }
}

This is especially convenient since you don't have to take care of hiding the keyboard ever again inside your views and it's not blocking any of your controls.

Note

This code is from Here

Also, I saw iOS13 - for non SwiftUI Cycle, this would be the equivalent: Here

Related