3

I am trying to add a keyboard toolbar for only some of my TextField's in SwiftUI.

I have a view defined like this:

struct Test: View {
    
    @State private var name: String = ""
    @State private var address: String = ""
    @State private var username: String = ""
    @State private var password: String = ""
    
    enum Field: Hashable {
        case nameField
        case addressField
        case usernameField
        case passwordField
    }
    @FocusState private var focusedField: Field?
    
    var body: some View {
        Form {
            Section {
                TextField("Name", text: $name)
                    .focused($focusedField, equals: .nameField)
                    .submitLabel(.next)
                
                TextField("Address", text: $address)
                    .focused($focusedField, equals: .addressField)
                    .submitLabel(.next)
                
                TextField("Username", text: $username)
                    .focused($focusedField, equals: .usernameField)
                    .submitLabel(.next)
                
                SecureField("Password", text: $password)
                    .focused($focusedField, equals: .passwordField)
                    .submitLabel(.done)
            }
        }
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                if focusedField == .addressField {
                    Button("Test", action: {})
                }
                Button("Done", action: {
                    print(focusedField)
                })
            }
        }
    }
}

The problem is, the additional toolbar button appears when the wrong field is selected.

enter image description here

I have also tried using the @FocusedValue like this:

...
@FocusedValue(\.field) var field: Field?
...
   TextField("Name", text: $name)
      .focused($focusedField, equals: .nameField)
      .submitLabel(.next)
      .focusedValue(\.field, .nameField)
...
      .focusedValue(\.field, .addressField)
...
      .focusedValue(\.field, .usernameField)
...
      .focusedValue(\.field, .passwordField)
...
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                if field == .addressField {
                    Button("Test", action: {})
                }
                Button("Done", action: {
                    print(field)
                })
            }
        }

But this gives the same result. It's as if the toolbar is decided, before the focused state is set. I'm not sure if this is a possible bug, or I am doing this wrong?

Although even when I get the above working, it doesn't fix my overall issue of only wanting the toolbar for 1 of the text fields, however when I try setting it like this, I get no toolbar at all.

.toolbar {
    ToolbarItemGroup(placement: .keyboard) {
        if field == .addressField {
            Button("Test", action: {})
        } else {
            EmptyView()
        }
    }
}
Darren
  • 10,182
  • 20
  • 95
  • 162
  • 1
    Seems like a bug, and I can't figure out a workaround. – George Sep 04 '21 at 17:00
  • 1
    Thanks, I've filed a bug report as even Apple's docs suggest this should work https://developer.apple.com/documentation/SwiftUI/ToolbarItemPlacement/keyboard?changes=_1 – Darren Sep 05 '21 at 07:47
  • You're not alone. Before I found your post, I just posted almost the same question - https://stackoverflow.com/questions/71401761/swiftui-keyboard-toolbar-conditional – kittonian Mar 08 '22 at 21:52

0 Answers0