2

I have à problem with TextEditor, I cannot hide the Keyboard after editing my text on the Texteditor.

    @State var monTexte: String = "
var body: some View {
        VStack {
            Spacer()
                .frame(height :15)
                .clipped()
            Text("Project ")
                .font(Font.system(size: 39.00))              
               .fontWeight(.black)
                .foregroundColor(Color.white)
                .multilineTextAlignment(.center)
                .padding(.all, 16.0)
                .clipped()
            
            TextEditor(text: $monTexte)
                .keyboardType(.alphabet)
                .font(.subheadline)
                .padding(.horizontal)
                .font(Font.system(size: 38.00))
                .frame(minWidth: 10, maxWidth: .infinity, minHeight: 10, maxHeight: 200, alignment: .topLeading)
                .border(Color.black)
                .clipped()
}
}
} 

I’ve found a method to hide the keyboard using a textfield but not using a TextEditor Coule you help me please

3
  • 1
    How do you define moment of after editing, ie. at which event you want to hide keyboard? Commented Jan 5, 2021 at 18:43
  • with a specific button or using the key return on the keyboard (for example), but and didn’t find the function to hide the keyboard Commented Jan 6, 2021 at 6:08
  • 1
    Keybord Return in TextEditor makes new line (it is not a TextField), but for some button you can use approach like in stackoverflow.com/questions/58349955/…. Commented Jan 6, 2021 at 6:31

5 Answers 5

3

I found this worked adequately for me. It's pure SwiftUI, without having to resort to UIKit.

struct TestView: View {
    @State private var response = ""
    @FocusState private var responseIsFocussed: Bool // dismiss response editor keyboard when hit Return

    var body: some View {
        TextEditor(text: $response)
            .focused($responseIsFocussed)
            .onReceive(response.publisher.last()) {
                if ($0 as Character).asciiValue == 10 { // ASCII 10 = newline
                    responseIsFocussed = false // unfocus TextEditor to dismiss keyboard
                    response.removeLast() // remove newline at end to prevent retriggering...
                }
            }
    }
}

The .focused() modifier on the view triggers attaches a trigger to the TextEditor to enable you to programmatically focus (show) or unfocus (dismiss) the keyboard. And the .onReceive() captures key entry; it checks whether the last char entered in the string is a newline (ASCII 10), and if so triggers the unfocus. Its important to immediately remove this Return/newline from the end of the string, otherwise it can keep triggering...

Caveat: this only triggers off the last char; if you edit the string and move the cursor midway and hit Return, nothing will happen (which actually behaves somewhat intuitively, IMO...)

Sign up to request clarification or add additional context in comments.

Comments

2

Thank you "Asperi" it's works using the code below :

var body: some View {
        VStack {
            Spacer()
                .frame(height :15)
                .clipped()
            Text("Project ")
                .font(Font.system(size: 39.00))              
               .fontWeight(.black)
                .foregroundColor(Color.white)
                .multilineTextAlignment(.center)
                .padding(.all, 16.0)
                .clipped()
                        HStack {
                Spacer()
                Button("Close Keyboard") {
                    UIApplication.shared.endEditing()

                }.font(Font.system(size: 20))
                .foregroundColor(Color.blue)
                
            }.clipped()
            TextEditor(text: $monTexte)
                .keyboardType(.alphabet)
                .font(.subheadline)
                .padding(.horizontal)
                .font(Font.system(size: 38.00))
                .frame(minWidth: 10, maxWidth: .infinity, minHeight: 10, maxHeight: 200, alignment: .topLeading)
                .border(Color.black)
                .clipped()
}
}
} 

//----------------------------------------------------//
// Masquer le clavier
//----------------------------------------------------//
extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}```

Comments

2

I prefer to use toolbar. This way you won't break new line logic. Suppose you have 2 TextEditors:

VStack {
    TextEditor(text: $subjectText)
       .focused($focusField, equals: .subject)
     TextEditor(text: $messageText)
       .focused($focusField, equals: .message)
}
  .toolbar {
      ToolbarItemGroup(placement: .keyboard) {
         Spacer()
         Button(focusField == .subject ? "Next" : "Done") {
            if focusField == .subject {
               focusField = .message
            } else {
               UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
               focusField = nil
            }
         }
      }
   }

Where

@FocusState private var focusField: Field?
enum Field: Hashable {
    case subject
    case message
}

1 Comment

That's the best, most native and most straightforward answer from all of the above. Thanks!
0

You can achieve this in SwiftUI by observing changes to your bound text with .onChange. If the last character is a newline ("\n"), you can programmatically remove it and dismiss the keyboard by un-focusing the editor using the @FocusState property wrapper.

import SwiftUI

struct SingleLineTextEditor: View {
    @State private var text: String = ""
    @FocusState private var isFocused: Bool

    var body: some View {
        TextEditor(text: $text)
            .focused($isFocused)
            .frame(height: 60)
            .onChange(of: text) { oldValue, newValue in
                if let last = newValue.last, last == "\n" {
                    isFocused = false       // Dismiss keyboard
                    text.removeLast()       // Remove the newline
                }
            }
            .background(Color(.systemGray6))
            .cornerRadius(8)
            .padding()
    }
}

Comments

-1

Like protspace, I prefer to allow the user to create new lines in the text editor. Here's a solution to this problem:

extension View {
    func hideKeyboard() {
        let resign = #selector(UIResponder.resignFirstResponder)
        UIApplication.shared.sendAction(resign, to: nil, from: nil, for: nil)
    }
}

And then attach this to the relevant part of your view (after the end of a Form {}, for example):

.toolbar {
     ToolbarItemGroup(placement: .keyboard) {
         Button("Dismiss keyboard") {
             hideKeyboard()
         }
         .buttonStyle(.borderedProminent)
      } // keyboard "Dismiss keyboard" button
} // End of toolbar

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.