I have text fields in my app that need to have a vertical axis (multi-lined) so the use can enter long textual inputs and easily see what they're doing. I would like to have a done button that lets them dismiss the onscreen keyboard or better yet, jump to the next field if there is one. I would really love a pure SwiftUI solution
I have tried
.submitLabel(.done)
, this creates the done button but it adds a new line when pressed, rather than dismissing the keyboard.onCommit
argument of TextField
and passing in a function that dismisses the keyboard. This works but you can't use both the onCommit
and axis
arguments on a given TextField
.lineLimit(nil)
, had no effectHStack
, which of couse had no effectYou can control the focus of a textfield (wether if it is active or not) with the @FocusState
wrapper in combination with the .focused(_)
modifier, like so:
import SwiftUI
struct ContentView: View {
// @FocusState can change the focus of a textfield (if it is active or not)
@FocusState var isEmail: Bool
@FocusState var isUsername: Bool
@FocusState var isPassword: Bool
@State var email: String = ""
@State var username: String = ""
@State var password: String = ""
var body: some View {
VStack {
TextField("Email", text: $email, axis: .horizontal)
.submitLabel(.continue)
.focused($isEmail) // connects the `isEmail` focus state value to the email textfield
.onSubmit() {
// on submit, when the user hits enter, the email focus gets removed and the username focus gets activated
isEmail = false
isUsername = true
}
TextField("Username", text: $username, axis: .horizontal)
.submitLabel(.continue)
.focused($isUsername)
.onSubmit() {
isUsername = false
isPassword = true
}
SecureField("Password", text: $password)
.submitLabel(.done)
.focused($isPassword)
.onSubmit() {
isPassword = false
}
}
.textFieldStyle(.roundedBorder)
.padding()
.onAppear {
isEmail = true // default focus when the view appears is the mail textfield
}
}
}