'Duplicate toolbar in SwiftUI

I added toolbar to 2 text fields, but the toolbar shows up twice:

This is the code for my custom text field:

public struct SUIDecimalField: View {
  public var body: some View {
    TextField(placeholder, text: $value)
      .focused(focused)
      .textFieldStyle(.roundedBorder)
      .keyboardType(.decimalPad)
      .toolbar {
        ToolbarItemGroup(placement: .keyboard) {
          HStack {
            Button(LOC(.clearKeyboardButton)) {
              value = ""
            }
            Spacer()
            Button(LOC(.dismissKeyboardButton)) {
              focused.wrappedValue = false
            }
          }
        }
      }
    }
  }

As you can see i only added the toolbar to the text field. I have 2 text fields, and it showed up twice.

Looks like the toolbar is somehow shared between all text fields. I am wondering how do I resolve it? I really want to put the toolbar inside the text field implementation so that the logic is encapsulated.

enter image description here



Solution 1:[1]

this is not ideal, but it might be a start:

struct ContentView: View {
    
    @State private var value1 = ""
    @State private var value2 = ""
    @FocusState private var focused: Int?
    
    var body: some View {
        Form {
            MyTextField(value: $value1, tag: 1, focused: $focused)
                .focused($focused, equals: 1)
            
            MyTextField(value: $value2, tag: 2, focused: $focused)
                .focused($focused, equals: 2)
        }
    }
}

struct MyTextField: View {
    
    @Binding var value: String
    var tag: Int
    var focused: FocusState<Int?>.Binding
    
    var body: some View {
        TextField("Test", text: $value)
            .textFieldStyle(.roundedBorder)
            .keyboardType(.decimalPad)
        
            .toolbar {
                ToolbarItemGroup(placement: .keyboard) {
                    HStack {
                        if focused.wrappedValue == tag {
                            Button("Clear") {
                                value = ""
                            }
                            Spacer()
                            Button("Done") {
                                focused.wrappedValue = nil
                            }
                        }
                    }
                }
            }
    }
}

Solution 2:[2]

Try applying the .toolbar modifier on the Form itself and not on each individual TextField like so:

import SwiftUI

struct ContentView: View {
    
    @State private var value1 = ""
    @State private var value2 = ""
    @FocusState private var focused: Int?
    
    var body: some View {
        Form {
            MyTextField(value: $value1, tag: 1, focused: $focused)
                .focused($focused, equals: 1)
            MyTextField(value: $value2, tag: 2, focused: $focused)
                .focused($focused, equals: 2)
        }
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                HStack {
                    Button("Clear") {
                        switch focused {
                        case 1: value1 = ""
                        case 2: value2 = ""
                        default: return
                        }
                    }
                    Spacer()
                    Button("Done") {
                        focused = nil
                    }
                }
            }
        }
    }
}

struct MyTextField: View {
    
    @Binding var value: String
    var tag: Int
    var focused: FocusState<Int?>.Binding
    
    var body: some View {
        TextField("Test", text: $value)
            .textFieldStyle(.roundedBorder)
            .keyboardType(.decimalPad)
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ChrisR
Solution 2 pxlshpr