Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 433 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to hide keyboard when using SwiftUI?

#21
# Keyboard's `Return` Key

In addition to all answers about tapping outside of the textField, you may want to dismiss the keyboard when the user taps the return key on the keyboard:

define this global function:

```
func resignFirstResponder() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
```

And add use in `onCommit` argument it:

```
TextField("title", text: $text, onCommit: {
resignFirstResponder()
})
```

### Benefits
- You can call it from anywhere
- It's not dependent on UIKit or SwiftUI (can be used in mac apps)
- It works even in iOS 13

### Demo
![demo][1]

[1]:
Reply

#22
SwiftUI released on June/2020 with Xcode 12 and iOS 14 adds hideKeyboardOnTap() modifier. This should solve your case number 2.
The solution for your case number 1 comes for free with Xcode 12 and iOS 14: the default keyboard for TextField hides automatically when the Return button is pressed.
Reply

#23
After a lot of attempts I found a solution that (currently) doesn't block any controls - adding gesture recognizer to `UIWindow`.

1. If you want to close keyboard only on Tap outside (without handling drags) - then it's enough to use just `UITapGestureRecognizer` and just copy step 3:
2. Create custom gesture recognizer class that works with any touches:

class AnyGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if let touchedView = touches.first?.view, touchedView is UIControl {
state = .cancelled

} else if let touchedView = touches.first?.view as? UITextView, touchedView.isEditable {
state = .cancelled

} else {
state = .began
}
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
state = .ended
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
state = .cancelled
}
}
3. In `SceneDelegate.swift` in the `func scene`, add next code:

let tapGesture = AnyGestureRecognizer(target: window, action:#selector(UIView.endEditing))
tapGesture.requiresExclusiveTouchType = false
tapGesture.cancelsTouchesInView = false
tapGesture.delegate = self //I don't use window as delegate to minimize possible side effects
window?.addGestureRecognizer(tapGesture)

4. Implement `UIGestureRecognizerDelegate` to allow simultaneous touches.

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


Now any keyboard on any view will be closed on touch or drag outside.

P.S. If you want to close only specific TextFields - then add and remove gesture recognizer to the window whenever called callback of TextField `onEditingChanged`
Reply

#24
Based on @Sajjon's answer, here is a solution allowing you to dismiss keyboard on tap, long press, drag, magnification and rotation gestures according to your choice.

This solution is working in XCode 11.4

# Usage to get the behavior asked by @IMHiteshSurani

```swift
struct MyView: View {
@State var myText = ""

var body: some View {
VStack {
DismissingKeyboardSpacer()

HStack {
TextField("My Text", text: $myText)

Button("Return", action: {})
.dismissKeyboard(on: [.longPress])
}

DismissingKeyboardSpacer()
}
}
}

struct DismissingKeyboardSpacer: View {
var body: some View {
ZStack {
Color.black.opacity(0.0001)

Spacer()
}
.dismissKeyboard(on: Gestures.allCases)
}
}
```

# Code

```swift
enum All {
static let gestures = all(of: Gestures.self)

private static func all<CI>(of _: CI.Type) -> CI.AllCases where CI: CaseIterable {
return CI.allCases
}
}

enum Gestures: Hashable, CaseIterable {
case tap, longPress, drag, magnification, rotation
}

protocol ValueGesture: Gesture where Value: Equatable {
func onChanged(_ action: @escaping (Value) -> Void) -> _ChangedGesture<Self>
}

extension LongPressGesture: ValueGesture {}
extension DragGesture: ValueGesture {}
extension MagnificationGesture: ValueGesture {}
extension RotationGesture: ValueGesture {}

extension Gestures {
@discardableResult
func apply<V>(to view: V, perform voidAction: @escaping () -> Void) -> AnyView where V: View {

func highPrio<G>(gesture: G) -> AnyView where G: ValueGesture {
AnyView(view.highPriorityGesture(
gesture.onChanged { _ in
voidAction()
}
))
}

switch self {
case .tap:
return AnyView(view.gesture(TapGesture().onEnded(voidAction)))
case .longPress:
return highPrio(gesture: LongPressGesture())
case .drag:
return highPrio(gesture: DragGesture())
case .magnification:
return highPrio(gesture: MagnificationGesture())
case .rotation:
return highPrio(gesture: RotationGesture())
}
}
}

struct DismissingKeyboard: ViewModifier {
var gestures: [Gestures] = Gestures.allCases

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

return gestures.reduce(AnyView(content)) { $1.apply(to: $0, perform: action) }
}
}

extension View {
dynamic func dismissKeyboard(on gestures: [Gestures] = Gestures.allCases) -> some View {
return ModifiedContent(content: self, modifier: DismissingKeyboard(gestures: gestures))
}
}
```
Reply

#25
I prefer using the `.onLongPressGesture(minimumDuration: 0)`, which does not cause the keyboard to blink when another `TextView` is activated (side effect of `.onTapGesture`). The hide keyboard code can be a reusable function.

.onTapGesture(count: 2){} // UI is unresponsive without this line. Why?
.onLongPressGesture(minimumDuration: 0, maximumDistance: 0, pressing: nil, perform: hide_keyboard)

func hide_keyboard()
{
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
Reply

#26
My solution how to hide software keyboard when users tap outside.
You need to use `contentShape` with `onLongPressGesture` to detect the entire View container. `onTapGesture` required to avoid blocking focus on `TextField`. You can use `onTapGesture` instead of `onLongPressGesture` but NavigationBar items won't work.

```swift
extension View {
func endEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}

struct KeyboardAvoiderDemo: View {
@State var text = ""
var body: some View {
VStack {
TextField("Demo", text: self.$text)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.contentShape(Rectangle())
.onTapGesture {}
.onLongPressGesture(
pressing: { isPressed in if isPressed { self.endEditing() } },
perform: {})
}
}
```
Reply

#27
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)})
Reply

#28
Please check

[To see links please register here]


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

```swift
KeyboardAvoider {
VStack {
TextField()
TextField()
TextField()
TextField()
}

}
```
Reply

#29
This method allows you to **hide the keyboard** on **spacers!**

First add this function (Credit Given To: Casper Zandbergen, from

[To see links please register here]

)

extension Spacer {
public func onTapGesture(count: Int = 1, perform action: @escaping () -> Void) -> some View {
ZStack {
Color.black.opacity(0.001).onTapGesture(count: count, perform: action)
self
}
}
}

Next add the following 2 functions (Credit Given To: rraphael, from this question)

extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}

The function below would be added to your View class, just refer to the top answer here from rraphael for more details.

private func endEditing() {
UIApplication.shared.endEditing()
}

Finally, you can now simply call...

Spacer().onTapGesture {
self.endEditing()
}

This will make any spacer area close the keyboard now. No need for a big white background view anymore!

You could hypothetically apply this technique of `extension` to any controls you need to support TapGestures that do not currently do so and call the `onTapGesture` function in combination with `self.endEditing()` to close the keyboard in any situation you desire.
Reply

#30
@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)
Reply



Forum Jump:


Users browsing this thread:
2 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through