This functionality is possible with a custom UIViewRepresentable.
This code is will create a custom TextField from a UITextField and allow you to change the parameters like font and autocapitalizationType you had.
struct CustomTextField: UIViewRepresentable {
class Coordinator: NSObject, UITextFieldDelegate {
@Binding var text: String
@Binding var isEditing: Bool
var didBecomeFirstResponder = false
init(text: Binding<String>, editing: Binding<Bool>) {
_text = text
_isEditing = editing
}
func textFieldDidChangeSelection(_ textField: UITextField) {
text = textField.text ?? ""
}
func textFieldDidBeginEditing(_ textField: UITextField) {
isEditing = true
}
func textFieldDidEndEditing(_ textField: UITextField) {
isEditing = false
}
}
var placeholder = ""
@Binding var text: String
@Binding var isEditing: Bool
var isFirstResponder: Bool = false
var font = UIFont.systemFont(ofSize: 20)
var autocapitalization = UITextAutocapitalizationType.none
var autocorrection = UITextAutocorrectionType.default
var borderStyle = UITextField.BorderStyle.none
func makeUIView(context: UIViewRepresentableContext<CustomTextField>) -> UITextField {
let textField = UITextField(frame: .zero)
textField.delegate = context.coordinator
textField.placeholder = placeholder
textField.font = font
textField.autocapitalizationType = autocapitalization
textField.autocorrectionType = autocorrection
textField.borderStyle = borderStyle
return textField
}
func makeCoordinator() -> CustomTextField.Coordinator {
return Coordinator(text: $text, editing: $isEditing)
}
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<CustomTextField>) {
uiView.text = text
if isFirstResponder && !context.coordinator.didBecomeFirstResponder {
uiView.becomeFirstResponder()
context.coordinator.didBecomeFirstResponder = true
} else if !isFirstResponder && context.coordinator.didBecomeFirstResponder {
uiView.resignFirstResponder()
context.coordinator.didBecomeFirstResponder = false
}
}
}
Credit: This code is modified from an answer to a similar question by @MatteoPacini here.
I am assuming that PlainTextFieldStyle() is equivalent to UITextField.BorderStyle.none.
So in your View, to have the "Edit" Button bring up the keyboard and change to "Done" to lower the keyboard, your code would be:
Image(colorScheme == .light ? "user" : "userDark")
.resizable()
.frame(width: 30, height: 30)
CustomTextField(
placeholder: "Name",
text: $name,
isEditing: $isEditing,
isFirstResponder: isEditing,
font: .systemFont(ofSize: 20),
autocapitalization: .words,
autocorrection: .no,
borderStyle: .none
)
.padding(.leading, 5)
if name != localName {
Button(action: {
self.name = ""
}) {
Text("Update")
.font(.system(size: 15))
.fontWeight(.light)
.foregroundColor(colorScheme == .light ? Color.black : Color.white)
}
} else if name == localName {
Button(action: {
self.isEditing.toggle()
}) {
Text(self.isEditing ? "Cancel" : "Edit")
.font(.system(size: 15))
.fontWeight(.light)
.foregroundColor(colorScheme == .light ? Color.black : Color.white)
}
}
With a Bool indicating if the TextField is editing:
@State var isEditing = false
If the code you provided defines the cell of a List or Form, you might replace this with an IndexSet or Optional<IndexPath> of the editing cell.
Also, if you do not want the "Done" Button, simply change the Button to:
Button(action: {
self.isEditing = true
}) {
Text("Edit")
.font(.system(size: 15))
.fontWeight(.light)
.foregroundColor(colorScheme == .light ? Color.black : Color.white)
}
Tested on a Swift Playground in Xcode-beta-2
https://stackoverflow.com/a/56508132/13231930