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?

#1
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`.

Reply

#2
> First add the extension on your code

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


> Use it as a modifer to close the keyboard on pressing `Done` button.

.toolbar{
ToolbarItemGroup(placement: .keyboard){
Spacer()
Button("Done"){
UIApplication.shared.dismissKeyboard()
}
}
}

Reply

#3
extension UIView{

override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

}
}
Reply

#4
I'd like to point out that .onTapGesture might consume events meant for navigation links. You can alternatively use a drag gesture, this should not clash with the most common elements.

.gesture(
DragGesture().onEnded { value in
self.dismissKeyboard()
})

However, this can prevent swipeActions. I avoided this by adding the event at the background view inside my CoporateIdentity View:

struct CIView: View {
var displayView: AnyView

var body: some View {
ZStack{
Color("Background").edgesIgnoringSafeArea(.all)
.gesture(
DragGesture().onEnded { value in
self.dismissKeyboard()
})
displayView
}
.foregroundColor(Color("Foreground"))
}

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

This view can be used like this:

CIView(displayView: AnyView(YourView()))
Reply

#5
## **using `.onSubmit` and `@FocusState` on + iOS 15**

using `.onSubmit` and `@FocusState` you can dismiss the keyboard on any press of return, or you can decide another `TextField` to then receive focus:

```
struct ContentView: View {
private enum Field: Int, CaseIterable {
case username, password
}

@State private var username: String = ""
@State private var password: String = ""

@FocusState private var focusedField: Field?

var body: some View {
NavigationView {
Form {
TextField("Username", text: $username)
.focused($focusedField, equals: .username)
SecureField("Password", text: $password)
.focused($focusedField, equals: .password)
}
.onSubmit {
fieldInFocus = nil
}
}
}
}
```

Or if you want to use `.onSubmit` to bring focus to a different `TextField`:

```
.onSubmit {
} if fieldInFocus == .email {
fieldInFocus = .password
} else if fieldInFocus == .password {
fieldInFocus = nil
}
}
```
Reply

#6
**iOS 13+**

One simple hack for iOS13+ is to set a state variable for "disabled" for every single textfield. Obviously not ideal, but might get the job done in some cases.

Once you set `disabled = True`, then all linked responders automatically resign.


@State var isEditing: Bool
@State var text: String

....

TextField("Text", text: self.$text).disabled(!self.isEditing)
Reply

#7
Updated the answer, working with **Swift 5.7**:

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


and then using it where needed like for example as button action:

Button(action: {
// do stuff
UIApplication.shared.dismissKeyboard()
}, label: { Text("MyButton") })
Reply

#8
## iOS 15+

**(Done button above the keyboard)**

Starting with iOS 15 we can now use [`@FocusState`](

[To see links please register here]

) to control which field should be focused (see [this answer](

[To see links please register here]

) to see more examples).

We can also add `ToolbarItem`s directly above the keyboard.

When combined together, we can add a `Done` button right above the keyboard. Here is a simple demo:

[![enter image description here][1]][1]

```
struct ContentView: View {
private enum Field: Int, CaseIterable {
case username, password
}

@State private var username: String = ""
@State private var password: String = ""

@FocusState private var focusedField: Field?

var body: some View {
NavigationView {
Form {
TextField("Username", text: $username)
.focused($focusedField, equals: .username)
SecureField("Password", text: $password)
.focused($focusedField, equals: .password)
}
.toolbar {
ToolbarItem(placement: .keyboard) {
Button("Done") {
focusedField = nil
}
}
}
}
}
}
```

## iOS 14+

**(Tap anywhere to hide the keyboard)**

Here is an updated solution for **SwiftUI 2 / iOS 14** (originally proposed [here](

[To see links please register here]

) by Mikhail).

It doesn't use the `AppDelegate` nor the `SceneDelegate` which are missing if you use the SwiftUI lifecycle:
```
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
}
}
}

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 // set to `false` if you don't want to detect tap during other gestures
}
}
```
---

If you want to detect other gestures (not only *tap* gestures) you can use `AnyGestureRecognizer` as in Mikhail's [answer](

[To see links please register here]

):
```
let tapGesture = AnyGestureRecognizer(target: window, action: #selector(UIView.endEditing))
```
---

Here is an example how to detect simultaneous gestures except Long Press gestures:
```
extension UIApplication: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return !otherGestureRecognizer.isKind(of: UILongPressGestureRecognizer.self)
}
}
```


[1]:
Reply

#9
Answer from @Mikhail worked very well; it just has the issue that it cannot support dragging to select text within TextView - keyboard will close on tapping on the selected text. I extended his solution for AnyGesture below to provide better text editing user experience. (Answer from [How to check for a UITextRangeView?][1])

Any recommendations to optimise the while loop?

```
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 {

// Check if it is a subview of editable UITextView
if var touchedView = touches.first?.view {
while let superview = touchedView.superview {
if let view = superview as? UITextView, view.isEditable {
state = .cancelled
return
} else {
touchedView = superview
}
}
}

state = .began
}
}

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

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
state = .cancelled
}
}
```

[1]:

[To see links please register here]

%20to%20check%20for%20a%20UITextRangeView?
Reply

#10
Since iOS 15, you can use `@FocusState`

struct ContentView: View {

@Binding var text: String

private enum Field: Int {
case yourTextEdit
}

@FocusState private var focusedField: Field?

var body: some View {
VStack {
TextEditor(text: $speech.text.bound)
.padding(Edge.Set.horizontal, 18)
.focused($focusedField, equals: .yourTextEdit)
}.onTapGesture {
if (focusedField != nil) {
focusedField = nil
}
}
}
}
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

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