0

So I am working on a view where I want to have editable text which is only made editable via a button press. So basically, when pressing the "edit" button, a text field should be made editable, and the focus should be sent to the text field.

Here's how I have attempted to implement this:

struct MyView: View {
    @Binding var text: String
    @FocusState var isEditing
    var body: some View {
        HStack {
            TextField("Text", text: $text)
                .disabled(!isEditing)
                .focused($isEditing)
            Spacer()
            
            Button(isEditing ? "Done" : "Edit") {
                isEditing.toggle()
            }
        }
    }
}

So if I comment out the .disabled line, the focus behavior works as intended. However when the disabled call is there, pressing the edit button does not enable or focus the text field.

My best guess is that maybe the field cannot be focused because it's initially disabled?

Is there any way to achieve this behavior? I've also tried using a separate @State var for disabled and this has the same result.

sak
  • 2,612
  • 24
  • 55

1 Answers1

1

Yes you need to separate isEditing from isFocusOn, then make isFocusOn depends on isEditing like this

Updated by @sak request: change editing on focus

struct MyView: View {
    @Binding var text: String = ""
    @State private var isEditing: Bool = false
    @FocusState var isFocusOn: Bool
    var body: some View {
        HStack {
            if isEditing {
                TextField("Text", text: $text)
                    .focused($isFocusOn)
                    .onAppear {
                        DispatchQueue.main.async {
                            isFocusOn = true
                        }
                    }
            } else {
                TextField("Text", text: $text)
                    .disabled(true)
            }
            Spacer()
            Button(isEditing ? "Done" : "Edit") {
                isEditing.toggle()
            }
        }
        .onChange(of: isFocusOn) { newValue in
            if !newValue { isEditing = false }
        }
    }
}

Note that we don't set edit = true when it's on focus, otherwise the disabled will be useless

meomeomeo
  • 764
  • 4
  • 7
  • What I lose here is, if I change the focus not by toggling the button (i.e. tapping on another focusable element) then the view is still in `isEditing == true`. Is there any way to get it so that `isEditing` will toggle whenever `isFocused` is toggled, as well as the reverse? – sak Mar 06 '22 at 15:00
  • i've updated my answer base on your request – meomeomeo Mar 06 '22 at 15:35