简体   繁体   中英

How to make an "Edit" button for a textField in SwiftUI?

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)
}

This is what the textFields look like: 在此处输入图片说明

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

https://stackoverflow.com/a/56508132/13231930

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM