Reputation: 3258
Say we have the following view of two text fields:
struct ContentView: View {
@State private var first = ""
@State private var second = ""
var body: some View {
VStack {
TextField("First", text: $first)
.toolbar {
ToolbarItem(placement: .keyboard) {
Button("Test") { }
}
}
TextField("Second", text: $second)
}
}
}
The toolbar
modifier is applied only to the "first" text field. My expectation is therefore that it only shows up on the keyboard, when the "first" text field is in focus.
What happens in practice though, it that it also shows up when the "second" text field is in focus.
Is this intended behaviour? And if so, how can I have different keyboard toolbars for different text fields?
Upvotes: 5
Views: 2245
Reputation: 2245
You can define a selection
variable that gets set when your TextField
is selected.
Then, in your .toolbar
, you can check for what TextField
is being edited and then display your appropriate Button
.
Wrapping it in a NavigationView
does work, but it also causes layout issues. This solution will also work in a ForEach
loop.
struct ContentView: View {
@State private var first = ""
@State private var second = ""
@State private var selection: Int?
var body: some View {
VStack {
TextField("First", text: $first, onEditingChanged: { isEditing in
self.selection = isEditing ? 1 : nil
})
TextField("Second", text: $second, onEditingChanged: { isEditing in
self.selection = isEditing ? 2 : nil
})
}
.toolbar {
if selection == 1 {
ToolbarItemGroup(placement: .keyboard) {
Button("Test") { }
}
}
}
}
}
Note: This seems to only work on iOS 16+
Upvotes: 1
Reputation: 413
I'm a very new to SwiftUI, but you can use the isFocused
flag as a condition for adding item to the toolbar for each text field.
@FocusState private var isFirstFieldFocused: Bool
@State private var firstFieldValue: String = ""
var body: some View {
TextField("First label", text: $firstFieldValue)
.focused($isFirstFieldFocused)
.toolbar {
if isFirstFieldFocused {
ToolbarItemGroup(placement: .keyboard) {...}
}
}
}
Upvotes: 0
Reputation: 382
The only thing that I've found so far that solves this problem works, but doesn't feel right. It also generates some layout constraint warnings in the console.
If you wrap each TextField
in a NavigationView
each `TextField will have its own context and thus its own toolbar.
Something like this:
struct ContentView: View {
@State private var first = ""
@State private var second = ""
var body: some View {
VStack {
NavigationView {
TextField("First", text: $first)
.toolbar {
ToolbarItem(placement: .keyboard) {
Button("Test") { }
}
}
}
NavigationView {
TextField("Second", text: $second)
}
}
}
}
Upvotes: 1