I have some textFields that are already completed and I want to add some "Edit" buttons that will show the keyboard to the one that I press. Here is the code to one of the textFields:
Image(colorScheme == .light ? "user" : "userDark").resizable().frame(width: 30, height: 30)
TextField("Name", text: $name).textFieldStyle(PlainTextFieldStyle()).padding(.leading, 5).font(.system(size: 20))
.autocapitalization(.words)
.disableAutocorrection(true)
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 {
Text("Edit").font(.system(size: 15)).fontWeight(.light)
.foregroundColor(colorScheme == .light ? Color.black : Color.white)
}
It's very easy if you want to enable custom editMode to each different property. Here I am creating custom editMode for only name field you just create editMode for other field like contact number you provided in above image. First create an editMode property for every field like:
@State var nameInEditMode = false
@State var name = "Mr. Foo Bar"
Then your each field should look like this:
HStack {
Image(systemName: "person.circle").resizable().frame(width: 30, height: 30)
if nameInEditMode {
TextField("Name", text: $name).textFieldStyle(RoundedBorderTextFieldStyle()).padding(.leading, 5).font(.system(size: 20))
.autocapitalization(.words)
.disableAutocorrection(true)
} else {
Text(name).font(.system(size: 20))
}
Button(action: {
self.nameInEditMode.toggle()
}) {
Text(nameInEditMode ? "Done" : "Edit").font(.system(size: 20)).fontWeight(.light)
.foregroundColor(Color.blue)
}
}
For testing just copy, paste and run the above code then see it's amazing.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.