How to hide keyboard when using SwiftUI?

2020-01-27 02:53发布

How to hide keyboard using SwiftUI for below cases?

Case 1

I have TextField and I need to hide the keyboard when the user clicks the return button.

Case 2

I have TextField and I need to hide the keyboard when the user taps outside.

How I can do this using SwiftUI?

Note:

I have not asked a question regarding UITextField. I want to do it by using SwifUI(TextField).

13条回答
姐就是有狂的资本
2楼-- · 2020-01-27 03:20

SwiftUI in 'SceneDelegate.swift' file just add: .onTapGesture { window.endEditing(true)}

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(
                rootView: contentView.onTapGesture { window.endEditing(true)}
            )
            self.window = window
            window.makeKeyAndVisible()
        }
    }

this is enough for each View using keyboard in your app...

查看更多
对你真心纯属浪费
3楼-- · 2020-01-27 03:25

@RyanTCB's answer is good; here are a couple of refinements that make it simpler to use and avoid a potential crash:

struct DismissingKeyboard: ViewModifier {
    func body(content: Content) -> some View {
        content
            .onTapGesture {
                let keyWindow = UIApplication.shared.connectedScenes
                        .filter({$0.activationState == .foregroundActive})
                        .map({$0 as? UIWindowScene})
                        .compactMap({$0})
                        .first?.windows
                        .filter({$0.isKeyWindow}).first
                keyWindow?.endEditing(true)                    
        }
    }
}

The 'bug fix' is simply that keyWindow!.endEditing(true) properly should be keyWindow?.endEditing(true) (yes, you might argue it can't happen.)

More interesting is how you can use it. For example, suppose you have a form with multiple editable fields in it. Just wrap it like this:

Form {
    .
    .
    .
}
.modifier(DismissingKeyboard())

Now, tapping on any control that itself doesn't present a keyboard will do the appropriate dismiss.

(Tested with beta 7)

查看更多
Juvenile、少年°
4楼-- · 2020-01-27 03:25

Please check https://github.com/michaelhenry/KeyboardAvoider

Just include KeyboardAvoider {} on top of your main view and that's all.

KeyboardAvoider {
    VStack { 
        TextField()
        TextField()
        TextField()
        TextField()
    }

}
查看更多
你好瞎i
5楼-- · 2020-01-27 03:26

Because keyWindow is deprecated.

extension View {
    func endEditing(_ force: Bool) {
        UIApplication.shared.windows.forEach { $0.endEditing(force)}
    }
}
查看更多
够拽才男人
6楼-- · 2020-01-27 03:28

I experienced this while using a TextField inside a NavigationView. This is my solution for that. It will dismiss the keyboard when you start scrolling.

NavigationView {
    Form {
        Section {
            TextField("Receipt amount", text: $receiptAmount)
            .keyboardType(.decimalPad)
           }
        }
     }
     .gesture(DragGesture().onChanged{_ in UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)})
查看更多
老娘就宠你
7楼-- · 2020-01-27 03:29

Expanding on the answer by @Feldur (which was based on @RyanTCB's), here is an even more expressive and powerful solution allowing you to dismiss keyboard on other gestures than onTapGesture, you can specify which you want in the function call.

Usage

// MARK: - View
extension RestoreAccountInputMnemonicScreen: View {
    var body: some View {
        List(viewModel.inputWords) { inputMnemonicWord in
            InputMnemonicCell(mnemonicInput: inputMnemonicWord)
        }
        .dismissKeyboard(on: [.tap, .drag])
    }
}

Or using All.gestures (just sugar for Gestures.allCases

查看更多
登录 后发表回答