I'm using a modal to add names to a list. When the modal is shown, I want to focus the TextField automatically, like this:
I've not found any suitable solutions yet.
Is there anything implemented into SwiftUI already in order to do this?
Thanks for your help.
var modal: some View { NavigationView{ VStack{ HStack{ Spacer() TextField("Name", text: $inputText) // autofocus this! .textFieldStyle(DefaultTextFieldStyle()) .padding() .font(.system(size: 25)) // something like .focus() ?? Spacer() } Button(action: { if self.inputText != ""{ self.players.append(Player(name: self.inputText)) self.inputText = "" self.isModal = false } }, label: { HStack{ Text("Add \(inputText)") Image(systemName: "plus") } .font(.system(size: 20)) }) .padding() .foregroundColor(.white) .background(Color.blue) .cornerRadius(10) Spacer() } .navigationBarTitle("New Player") .navigationBarItems(trailing: Button(action: {self.isModal=false}, label: {Text("Cancel").font(.system(size: 20))})) .padding() } }
If you're supporting only iOS 15 and later, you can activate and dismiss the keyboard for a text field by focusing and unfocusing it. In its simplest form, this is done using the @FocusState property wrapper and the focusable() modifier – the first stores a Boolean that tracks whether the second is currently focused.
You just make a View with all the code you want for the SecureTextField and the TextField then all you have to do is call the HybridTextField where ever you need it. Save this answer.
Since Responder Chain is not presented to be consumed via SwiftUI, so we have to consume it using UIViewRepresentable. I have made a workaround that can work similarly to the way we use to do using UIKit.
struct CustomTextField: UIViewRepresentable { class Coordinator: NSObject, UITextFieldDelegate { @Binding var text: String @Binding var nextResponder : Bool? @Binding var isResponder : Bool? init(text: Binding<String>,nextResponder : Binding<Bool?> , isResponder : Binding<Bool?>) { _text = text _isResponder = isResponder _nextResponder = nextResponder } func textFieldDidChangeSelection(_ textField: UITextField) { text = textField.text ?? "" } func textFieldDidBeginEditing(_ textField: UITextField) { DispatchQueue.main.async { self.isResponder = true } } func textFieldDidEndEditing(_ textField: UITextField) { DispatchQueue.main.async { self.isResponder = false if self.nextResponder != nil { self.nextResponder = true } } } } @Binding var text: String @Binding var nextResponder : Bool? @Binding var isResponder : Bool? var isSecured : Bool = false var keyboard : UIKeyboardType func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField { let textField = UITextField(frame: .zero) textField.isSecureTextEntry = isSecured textField.autocapitalizationType = .none textField.autocorrectionType = .no textField.keyboardType = keyboard textField.delegate = context.coordinator return textField } func makeCoordinator() -> CustomTextField.Coordinator { return Coordinator(text: $text, nextResponder: $nextResponder, isResponder: $isResponder) } func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) { uiView.text = text if isResponder ?? false { uiView.becomeFirstResponder() } } }
You can use this component like this...
struct ContentView : View { @State private var username = "" @State private var password = "" // set true , if you want to focus it initially, and set false if you want to focus it by tapping on it. @State private var isUsernameFirstResponder : Bool? = true @State private var isPasswordFirstResponder : Bool? = false var body : some View { VStack(alignment: .center) { CustomTextField(text: $username, nextResponder: $isPasswordFirstResponder, isResponder: $isUsernameFirstResponder, isSecured: false, keyboard: .default) // assigning the next responder to nil , as this will be last textfield on the view. CustomTextField(text: $password, nextResponder: .constant(nil), isResponder: $isPasswordFirstResponder, isSecured: true, keyboard: .default) } .padding(.horizontal, 50) } }
Here isResponder is to assigning responder to the current textfield, and nextResponder is to make the first response , as the current textfield resigns it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With